Tworzenie rozszerzonego profilu użytkownika

Mam rozszerzony Model UserProfile w django:

class UserProfile(models.Model):
  user = models.ForeignKey(User, unique=True)
  #other things in that profile

I a signals.py:

from registration.signals import user_registered
from models import UserProfile
from django.contrib.auth.models import User

def createUserProfile(sender, instance, **kwargs):
  profile = users.models.UserProfile()
  profile.setUser(sender)
  profile.save()

user_registered.connect(createUserProfile, sender=User)

Upewniam się, że sygnał zostanie zarejestrowany, mając to w moim __init__.py:

import signals

Więc to powinno stworzyć mi Nowy UserProfile dla każdego użytkownika, który się zarejestruje, prawda? Ale tak nie jest. zawsze dostaję błędy "USERPROFILE matching query does not exist", gdy próbuję się zalogować, co oznacza, że wpis bazy danych nie istnieje.

Powinienem powiedzieć, że używam django-registration, które zapewnia sygnał user_registered.

Struktura ważnych aplikacji do tego jest taka, że mam jedną aplikację o nazwie "użytkownicy", tam mam: models.py, signals.py, urls.py oraz views.py (i kilka innych rzeczy, które nie powinny mieć tu znaczenia). Klasa UserProfile jest zdefiniowana w models.py.

Update : zmieniłem signals.py do:

from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User

def create_profile(sender, **kw):
    user = kw["instance"]
    if kw["created"]:
        profile = UserProfile()
        profile.user = user
        profile.save()

post_save.connect(create_profile, sender=User)

Ale teraz dostaję "IntegrityError":

"column user_id nie jest unikalny"

Edytuj 2:

Znalazłem. Wygląda na to, że zarejestrowałem sygnał dwa razy. Obejście tego problemu zostało opisane tutaj: http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave

Musiałem dodać dispatch_uid, teraz mój signals.py wygląda tak i działa:

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from models import UserProfile
from django.db import models

def create_profile(sender, **kw):
    user = kw["instance"]
    if kw["created"]:
        profile = UserProfile(user=user)
        profile.save()

post_save.connect(create_profile, sender=User, dispatch_uid="users-profilecreation-signal")
Author: mlissner, 2009-12-15

6 answers

Możesz zaimplementować go używając post_save na użytkowniku:

from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User

def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        profile = users.models.UserProfile()
        profile.setUser(sender)
        profile.save()

post_save.connect(create_profile, sender=User)

Edit:
Inne możliwe rozwiązanie, które jest testowane i działa (używam go na mojej stronie):

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        up = UserProfile(user=user, stuff=1, thing=2)
        up.save()
post_save.connect(create_profile, sender=User)
 28
Author: Agos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-08 16:01:53

Możesz utworzyć Rozszerzony profil, gdy po raz pierwszy uzyskasz dostęp dla każdego użytkownika:

from django.db import models
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    additional_info_field = models.CharField(max_length=50)

User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])

Następnie użyj

from django.contrib.auth.models import User
user = User.objects.get(pk=1)
user.profile.additional_info_field

Ref: http://www.codekoala.com/blog/2009/quick-django-tip-user-profiles/

 6
Author: Tim Abell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-01 23:00:44

To mi pomogło: primary_key=True

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True, primary_key=True, related_name="user")
    phone = models.CharField(('phone'),max_length=30, blank=False, null=True)
    user_building = models.ManyToManyField(Building, blank=True)
    added_by = models.ForeignKey(User, blank=True, null=True, related_name="added")
 6
Author: Vári Zorán,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-28 13:26:01

Kiedy wywołujesz profile.setUser(), myślę, że chcesz przekazać instance zamiast sender jako parametr.

Z dokumentacji sygnału user_registered, sender odnosi się do klasy User; {[1] } jest rzeczywistym obiektem użytkownika, który został zarejestrowany.

 5
Author: Ben James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-15 22:54:15

Według moich najnowszych badań, tworzenie osobnego pliku, np. singals.py, nie działa.

Lepiej podłącz 'create_profile' do 'post_save' w swoim models.py bezpośrednio, w przeciwnym razie ten fragment kodu nie zostanie wykonany, ponieważ jest w osobnym pliku i nikt go nie importuje.

Mój ostatni kod w celach informacyjnych:

# models.py

# Here goes the definition of class UserProfile.
class UserProfile(models.Model):
    ...

# Use signal to automatically create user profile on user creation.

# Another implementation:
# def create_user_profile(sender, **kwargs):
#     user = kwargs["instance"]
#     if kwargs["created"]:
#         ...
def create_user_profile(sender, instance, created, **kwargs):
    """
    :param sender: Class User.
    :param instance: The user instance.
    """
    if created:
        # Seems the following also works:
        #   UserProfile.objects.create(user=instance)
        # TODO: Which is correct or better?
        profile = UserProfile(user=instance)
        profile.save()

post_save.connect(create_user_profile,
                  sender=User,
                  dispatch_uid="users-profilecreation-signal")
 1
Author: Adam Gu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 01:48:11

Aktualizacja dla 2018:

To pytanie zebrało wiele opinii, może nadszedł czas na aktualizację.

To jest najnowsza wersja dla najnowszego Django.

from django.dispatch import receiver
from django.db.models.signals import post_save
from django.conf import settings
from models import UserProfile

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance=None, created=False, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
 0
Author: Oliver Ni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-30 04:02:38