2009-12-15 7 views
44

J'ai un modèle UserProfile étendu dans django:Création d'un profil d'utilisateur étendu

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

Et 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 fais que le signal est enregistré en ayant dans mon __init__.py :

import signals 

Donc, cela devrait créer un nouveau UserProfile pour chaque utilisateur qui enregistre, rig ht? Mais ce n'est pas le cas. Je reçois toujours des erreurs "UserProfile matching query does not exists" lorsque j'essaie de me connecter, ce qui signifie que l'entrée de la base de données n'est pas là.

Je devrais dire que j'utilise django-registration, qui fournit le signal enregistré par l'utilisateur. La structure des applications importantes pour cela est, que j'ai une application appelée "utilisateurs", j'ai là: models.py, signals.py, urls.py et views.py (et d'autres choses qui devraient c'est important 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, je reçois un "IntegrityError":

"colonne user_id n'est pas unique"

Édition 2:

Je l'ai trouvé. On dirait que j'ai enregistré le signal deux fois. La solution de contournement pour ce qui est décrit ici: http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave

je devais ajouter un dispatch_uid, maintenant mon signals.py ressemble à ceci et travaille:

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") 
+0

Pouvez-vous poster la structure de votre application django. Je suis curieux de connaître quelques lignes dans votre code comme 'profile = user.models.UserProfile()' - avez-vous un module nommé 'user'? Où est UserProfile() situé. – czarchaic

+0

c'est les utilisateurs, je ne sais pas comment cette faute de frappe est arrivée, mais le problème est le même. Je me demande pourquoi python n'a pas jeté une erreur pour le chemin mal orthographié. – Kai

+0

merci pour cette solution, im nouveau avec django, et je ne sais pas comment enregistrer d'autres données sur le profil de l'utilisateur. Je vois que vous venez de sauvegarder l'utilisateur dans le modèle UserProfile, mais comment enregistrer les données d'autres (en utilisant votre signals.py) à partir du formulaire d'inscription? Thansk (désolé avec l'anglais) – Asinox

Répondre

27

Vous pouvez la mettre en œuvre à l'aide 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é 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) 
+1

doit être "profile.setUser (user)", je pense. Mais alors je reçois "column user_id n'est pas unique". Des pensées à ce sujet? – Kai

+0

J'ai ajouté une autre solution possible à ma réponse, vérifiez-la. – Agos

+0

Je reçois "colonne id_utilisateur n'est pas unique", pouvez-vous s'il vous plaît montrez-moi votre modèle UserProfile? Peut-être que j'ai quelque chose avec le ForeignKey() mal. – Kai

5

Lorsque vous appelez profile.setUser(), je pense que vous voulez passer instance plutôt que sender comme paramètre. De la documentation of the user_registered signal, sender fait référence à la classe User; instance est l'objet utilisateur réel qui a été enregistré.

6

Vous pouvez obtenir le profil étendu à être créé lors du premier accès 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 

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

6

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") 
+2

primary_key = True implique null = False et unique = True. https://docs.djangoproject.com/fr/dev/ref/models/fields/ – flyingfoxlee

1

Selon mes dernières recherches, la création d'un fichier séparé, par exemple, singals.py , ne marche pas. Il vaut mieux connecter 'create_profile' à 'post_save' directement dans votre fichier models.py, sinon ce morceau de code ne sera pas exécuté car il se trouve 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") 
Questions connexes