La création d'un profil utilisateur

j'ai une longue UserProfile modèle dans django:

class UserProfile(models.Model):
  user = models.ForeignKey(User, unique=True)
  #other things in that profile
<!--6 et 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)

Je m'assure que le signal est enregistré en ayant ceci dans mon __init__.py:

import signals

donc cela devrait me créer un nouveau profil utilisateur pour chaque utilisateur qui s'enregistre, non? Mais ce n'est pas le cas. J'ai toujours des erreurs "UserProfile matching query does not exist" quand j'essaie de me connecter, ce qui signifie que l'entrée de la base de données n'est pas là.

je dois dire que j'ai utilisez django-registration, qui fournit le signal user_registered.

la structure des applications importantes pour cela est, que j'ai une application appelée "utilisateurs", là j'ai: models.py, signals.py, urls.py et views.py (et d'autres choses qui ne devraient pas avoir d'importance ici). La classe UserProfile est définie dans models.py.

mise à Jour: j'ai changé le signals.py à:

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)

Mais maintenant j'ai un "IntegrityError":

"colonne user_id n'est pas unique"

Edit 2:

je l'ai trouvé. On dirait que j'ai enregistré le signal deux fois. La solution est décrite ici: http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave

j'ai dû ajouter un dispatch_uid, maintenant mon signals.py ressemble et fonctionne:

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
demandé sur mlissner 2009-12-15 23:58:12

6 réponses

vous pouvez l'implémenter en utilisant post_save sur l'utilisateur:

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:

Une autre solution possible, qui est testée et fonctionne (je l'utilise sur mon 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)
28
répondu Agos 2015-07-08 16:01:53

vous pouvez obtenir le profil étendu à créer lors de la première consultation pour chaque utilisateur à la place:

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

puis utilisez

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

réf:http://www.codekoala.com/blog/2009/quick-django-tip-user-profiles/

6
répondu Tim Abell 2011-05-01 23:00:44

cela m'a aidé: 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
répondu Vári Zorán 2012-03-28 13:26:01

Lorsque vous appelez profile.setUser(), je pense que vous voulez passer instance plutôt que sender en tant que paramètre.

la documentation de la user_registered signal,sender se réfère à la User classe; instance est l'objet utilisateur réel qui a été enregistré.

5
répondu Ben James 2009-12-15 22:54:15

selon mes dernières recherches, la création d'un fichier séparé, par exemple, singals.py, ne fonctionne pas.

Vous feriez mieux de connecter 'create_profile' à 'post_save' dans votre models.py directement, sinon ce morceau de code ne sera pas exécuté puisqu'il est dans un fichier séparé et personne ne l'importe.

Mon code final pour votre référence:

# 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
répondu Adam Gu 2017-07-19 01:48:11

mise à jour pour 2018:

cette question a recueilli beaucoup de points de vue, il est peut-être temps de la mettre à jour.

C'est la dernière version pour le dernier 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
répondu Oliver Ni 2018-03-30 04:02:38