Question

J'ai un modèle UserProfile étendu à Django:

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

Et un 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 cela dans mon __init__.py:

import signals

Cela devrait donc me créer un nouveau utilisateur pour chaque utilisateur qui enregistre, non? Mais ce n'est pas le cas. J'obtiens toujours des erreurs "UserProfile Matching Exist n'existe pas" lorsque 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'utilise un inscription Django, qui fournit le signal User_Register.

La structure des applications importantes pour cela est que j'ai une application appelée "utilisateurs", là j'ai: modèles.py, signals.py, urls.py et vues.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é les signaux.py en:

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, je reçois une "EnergityError":

"Column User_id n'est pas unique"

Edit 2:

Je l'ai trouvé. On dirait que j'ai enregistré le signal deux fois. La solution de contournement est décrite ici: http://code.djangoproject.com/wiki/signals#helpost_saveseemstobemittetswiceforeachsave

J'ai dû ajouter un Dispatch_Uid, maintenant mes signaux.py ressemble à ceci et fonctionnent:

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")
Était-ce utile?

La solution

Vous pouvez l'implémenter à l'aide de 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)

Éditer:
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)

Autres conseils

Vous pouvez obtenir le profil étendu à créer lors de la première fois pour la première fois pour chaque utilisateur:

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 utiliser

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/

Cela m'a aidé: primaire_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")

Quand vous appelez profile.setUser(), Je pense que tu veux passer instance plutôt que sender comme le paramètre.

Du Documentation du signal User_Register, sender se réfère à la User classer; instance est l'objet utilisateur réel qui a été enregistré.

Selon mes dernières recherches, la création d'un fichier séparé, EG, Singals.py, ne fonctionne pas.

Vous feriez mieux de connecter 'create_profile' à 'post_save' dans vos modèles.py directement, sinon ce morceau de code ne sera pas exécuté car 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")

Mise à jour pour 2018:

Cette question a recueilli beaucoup de vues, il est peut-être temps pour une mise à jour.

Il s'agit de la dernière version du 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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top