it-swarm-pt.tech

Criando um perfil de usuário estendido

Eu tenho um modelo UserProfile estendido no Django:

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

E um 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)

Eu me certifico de que o sinal seja registrado tendo isto em meu __init__.py:

import signals

Então, isso deve me criar um novo UserProfile para cada usuário que se registra, certo? Mas isso não acontece. Eu sempre recebo erros "consulta de perfil do usuário não existe" quando tento fazer logon, o que significa que a entrada do banco de dados não está lá.

Eu devo dizer que eu uso o Django-registration, que fornece o sinal user_registered.

A estrutura dos aplicativos importantes para isso é que eu tenho um aplicativo chamado "users", lá eu tenho: models.py, signals.py, urls.py e views.py (e algumas outras coisas que não deveriam importar aqui ). A classe UserProfile é definida em models.py.

Update : eu mudei o signals.py para:

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)

Mas agora eu recebo um "IntegrityError":

"coluna user_id não é única"

Editar 2:

Eu encontrei. Parece que, de alguma forma, registrei o sinal duas vezes. A solução alternativa para isso é descrita aqui: http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave

Eu tive que adicionar um dispatch_uid, agora meu signals.py se parece com isso e está funcionando:

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")
45
Kai

Você pode implementá-lo usando post_save no usuário:

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)

Editar:
Outra solução possível, que é testada e funciona (estou usando no meu site):

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)
29
Agos

Isso me ajudou: 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
Vári Zorán

Você pode obter o perfil estendido a ser criado quando acessado pela primeira vez para cada usuário:

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])

então use

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
Tim Abell

Quando você chama profile.setUser(), eu acho que você quer passar instance em vez de sender como o parâmetro.

A partir da documentação de do sinal registrado pelo usuário , sender refere-se à classe User; instance é o objeto de usuário real que foi registrado.

5
Ben James

De acordo com minha pesquisa mais recente, a criação de um arquivo separado, por exemplo, singals.py, não funciona.

É melhor conectar o 'create_profile' ao 'post_save' no seu models.py diretamente, caso contrário, este pedaço de código não será executado, pois está em um arquivo separado e ninguém o importa.

Meu código final para sua referência:

# 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
Adam Gu

Atualização para 2018:

Esta questão coletou muitas visualizações, talvez seja hora de uma atualização.

Esta é a versão mais recente do Django mais recente.

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
Oliver Ni