2010-09-14 21 views
18

Uso request.user.get_profile() en varios lugares de mi código. Sin embargo, no todos los usuarios tienen un perfil de usuario asociado con su cuenta. ¿Existe alguna manera de que pueda crear un perfil de usuario automáticamente al llamar al request.user.get_profile() si no tienen uno sin tener que cambiar cada una de mis llamadas request.user.get_profile()? Tal vez usando señales o algo.Django create userprofile si no existe

El problema que tengo es que utilizo un inicio de sesión único, así que si alguien inicia sesión en otro sistema y luego va a mi sitio, se conectan pero no se crea un perfil de usuario (creo un usuario perfil cuando inician sesión).

+0

se puede comprobar por favor esta pregunta para http://stackoverflow.com/questions/17806683/create-row -de-date-while-creating-superuser que estoy enfrentando problema, no puedo venir – user2086641

Respuesta

22

Normalmente, los objetos de perfil de usuario se crean justo después de que se crea la instancia de usuario. Esto se logra fácilmente usando señales.

The problem I have is that I use a single sign-in login so if someone logs in on another system and then goes to my site they are logged in but don't get a user profile created (I create a user profile when they log in).

Al parecer, el uso de señales en el momento de creación del usuario no funcionará para usted. Una forma de lograr lo que está tratando de hacer sería reemplazar llamadas al request.user.get_profile() con una función personalizada. Diga get_or_create_user_profile(request). Esta función puede intentar recuperar el perfil de un usuario y luego crearlo sobre la marcha si no existe.

Por ejemplo:

def get_or_create_user_profile(request): 
    profile = None 
    user = request.user 
    try: 
     profile = user.get_profile() 
    except UserProfile.DoesNotExist: 
     profile = UserProfile.objects.create(user, ...) 
    return profile 
+1

Gracias. Me gusta esta respuesta, pero no me interesaba cambiar todas las instancias de request.user.get_profile() en mi código. ¿No hay una señal que pueda adjuntar al perfil de usuario post_get (no sé si existe) – John

+0

@John: AFAIK no hay señal incorporada que se envíe en 'get' (' post_get' como dijiste). Los documentos parecen estar de acuerdo http://docs.djangoproject.com/en/dev/ref/signals/ –

+0

¿qué ocurre al hacerlo a través de middleware? – John

3

encontré esta solución me gusta usar en este sitio: http://www.turnkeylinux.org/blog/django-profile

User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0]) 

El uso de una propiedad como esta parece más limpio que la definición de un nuevo método, pero estoy de acuerdo Sería una molestia pasar por su código base y cambiar las referencias user.get_profile() a user.profile.

Por otra parte, ¿no es así para qué sirve la función de búsqueda y reemplazo de archivos globales?

+0

Normalmente, el primer usuario (superusuario) no creará su perfil porque fue creado durante './manage.py startapp'. – hobbes3

+2

El problema con esta solución es que golpeará la base de datos para recuperar el perfil cada vez que haga referencia a User.profile. p.ej. si hace algo como: User.profile.field = "derp" y luego User.profile.save(), volverá a cargar .profile desde el archivo db y perderá los cambios antes de guardar. El punto es que es un mal uso de las propiedades. Use un método en su lugar para esa funcionalidad. Imo – sqwerty

+0

Hmm. No creo que este sea un mal uso de las propiedades. Voy a publicar una mejora sin embargo. –

3

Sobre la base de la respuesta de bskinner y en respuesta al comentario de sqwerty, es posible utilizar este:

def get_or_create_profile(user): 
    """ 
    Return the UserProfile for the given user, creating one if it does not exist. 

    This will also set user.profile to cache the result. 
    """ 
    user.profile, c = UserProfile.objects.get_or_create(user=user) 
    return user.profile 

User.profile = property(get_or_create_profile) 

Así que esto va a crear un perfil, si es necesario, y luego User.profile.field = "deep"User.profile.save() obras.

1

Se revisó como a continuación. De lo contrario, se mostrará "AttributeError: no se puede establecer el atributo". El permiso de asignación del guardián es opcional aquí.

 
def get_or_create_profile(user): 
    profile, created = UserProfile.objects.get_or_create(user=user) 
    assign('change_userprofile', user, profile) 
    assign('delete_userprofile', user, profile) 
    return profile 

User.profile = property(get_or_create_profile) 
1

Aquí hay un comando de administración rápida que se puede usar para crear perfiles predeterminados para los usuarios que carecen de ellos. Con esto en su lugar puede ejecutar ./manage.py missing_profiles en cualquier momento, o añadirlo a una tarea programada, etc.

from django.core.management.base import BaseCommand 
from django.contrib.auth.models import User 
from people.models import Profile 

''' 
Create default profiles for any User objects that lack them. 
''' 


class Command(BaseCommand): 
    help = "Create default profiles for any User objects that lack them." 

    def handle(self, *args, **options): 
     users = User.objects.filter(profile=None) 
     for u in users: 
      Profile.objects.create(user=u) 
      print("Created profile for {u}".format(u=u))