2009-12-15 46 views
44

tengo un modelo extendido PerfilUsuario en Django:Creación de un perfil de usuario extendida

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

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

que asegurarse de que la señal se registró por tener esto en mi __init__.py :

import signals 

Así que eso debería crearme un nuevo perfil de usuario para cada usuario que se registre, rig ¿ht? Pero no es así Siempre obtengo errores de "La coincidencia de perfil de usuario no existe" cuando intento iniciar sesión, lo que significa que la entrada de la base de datos no está allí.

Debo decir que uso django-registration, que proporciona la señal user_registered.

La estructura de las aplicaciones importantes para esto es que tengo una aplicación llamada "usuarios", allí tengo: models.py, signals.py, urls.py y views.py (y algunas otras cosas que no deberían tener) no importa aquí). La clase UserProfile se define en models.py.

actualización: Me cambió el signals.py a:

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) 

Pero ahora me sale un "IntegrityError":

"user_id columna no es único"

Editar 2:

Lo encontré. Parece que de alguna manera registré la señal dos veces. La solución para esto se describe aquí: http://code.djangoproject.com/wiki/Signals#Helppost_saveseemstobeemittedtwiceforeachsave

he tenido que añadir un dispatch_uid, ahora mi signals.py se parece a esto y está trabajando:

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

Podría publicar la estructura de su aplicación Django. Tengo curiosidad acerca de un par de líneas en tu código como 'profile = user.models.UserProfile()' - ¿tienes un módulo llamado 'usuario'? Dónde se encuentra UserProfile(). – czarchaic

+0

son usuarios, no sé cómo llegó ese error, pero el problema es el mismo. Me pregunto por qué Python no arrojó un error para la ruta mal escrita. – Kai

+0

gracias por esta solución, soy nuevo con django, y no sé cómo ahorrar otros datos sobre el perfil del usuario. veo que solo guarde al usuario en el perfil UserProfile, pero ¿qué tan bueno guarde los datos de otros (utilizando su signals.py) desde el formulario de registro? Thansk (lo siento con el inglés) – Asinox

Respuesta

27

Puede hacerlo operativo post_save en el usuario:

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:
Otra posible solución, que está probado y funciona (lo estoy usando en mi sitio):

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

tiene que ser "profile.setUser (usuario)", creo. Pero luego aparece "column user_id no es único". ¿Alguna idea sobre eso? – Kai

+0

Agregué otra posible solución a mi respuesta, échale un vistazo. – Agos

+0

Me sale "column user_id no es único", ¿me puede mostrar su modelo de UserProfile? Tal vez tengo algo con ForeignKey() mal. – Kai

5

Cuando se llama a profile.setUser(), creo que desea pasar instance en lugar de sender como el parámetro.

Desde documentation of the user_registered signal, sender se refiere a la clase User; instance es el objeto de usuario real que se registró.

6

Puede obtener el perfil ampliado que se creará cuando se acceda por primera vez para cada usuario:

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

a continuación, utilizar

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

Esto me ayudó: 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 implica null = False y unique = True. https://docs.djangoproject.com/en/dev/ref/models/fields/ – flyingfoxlee

1

Según mi última investigación, la creación de un archivo separado, por ejemplo, singals.py , No funciona.

Será mejor que conecte 'create_profile' a 'post_save' en su models.py directamente, de lo contrario este fragmento de código no se ejecutará ya que está en un archivo separado y nadie lo importa.

Mi código final para su referencia:

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