Domanda

Ho un modello esteso di profilo in django:

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

E un segnali.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)

Mi assicuro che il segnale venga registrato avendo questo nel mio __init__.py:

import signals

Quindi questo dovrebbe crearmi un nuovo profilo di utente per ogni utente che registra, giusto? Ma non lo è. Ricevo sempre errori "UserProfile corrispondente non esiste errori quando provo ad accedere, il che significa che la voce del database non è lì.

Dovrei dire che uso Django-Registration, che fornisce il segnale User_Register.

La struttura delle app importanti per questo è che ho un'applicazione chiamata "utenti", qui ho: models.py, segnals.py, urlspy e views.py (e altre cose che non dovrebbero importare qui ). La classe UserProfile è definita in models.py.

Aggiornare: Ho cambiato segnali.py in:

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)

Ma ora ricevo un "integrityError":

"La colonna user_id non è univoca"

EDIT 2:

L'ho trovato. Sembra che in qualche modo ho registrato il segnale due volte. La soluzione alternativa per questo è descritta qui: http://code.djangoproject.com/wiki/signals#helppost_saveseemstobeembetedtwiceforeachsave

Ho dovuto aggiungere un dispatch_uid, ora i miei segnali.py sembrano questo e funziona:

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")
È stato utile?

Soluzione

È possibile implementarlo usando Post_Save sull'utente:

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)

Modificare:
Un'altra possibile soluzione, che viene testata e funziona (la sto usando sul mio sito):

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)

Altri suggerimenti

È possibile creare il profilo esteso da creare al primo accesso per ciascun utente:

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

Quindi usa

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

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

Questo mi ha aiutato: primario_key = vero

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

Quando chiami profile.setUser(), Penso che tu voglia passare instance piuttosto che sender come parametro.

Dal Documentazione del segnale User_register, sender si riferisce a User classe; instance è l'oggetto utente reale che è stato registrato.

Secondo la mia ultima ricerca, la creazione di un file separato, ad es. Singals.py, non funziona.

È meglio connettere "create_profile" a "post_save" nei tuoi modelli.py direttamente, altrimenti questo pezzo di codice non verrà eseguito poiché è in un file separato e nessuno lo importa.

Il mio codice finale per il tuo riferimento:

# 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")

Aggiornamento per il 2018:

Questa domanda ha raccolto molte opinioni, forse è tempo di un aggiornamento.

Questa è l'ultima versione per l'ultima 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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top