2010-09-14 31 views
18

Io uso request.user.get_profile() in un numero di punti nel mio codice. Tuttavia, non tutti gli utenti hanno un profilo utente associato al proprio account. C'è un modo in cui posso creare automaticamente un profilo utente quando si chiama request.user.get_profile() se non ne hanno uno senza dover cambiare ciascuna delle mie chiamate request.user.get_profile(). Forse usando segnali o qualcosa.Django crea profilo utente se non esiste

Il problema che ho è che utilizzo un accesso di accesso singolo, quindi se qualcuno accede a un altro sistema e poi va al mio sito, ha effettuato l'accesso ma non ottiene un profilo utente creato (creo un utente profilo quando si collegano).

+0

può si prega di controllare questa domanda SO http://stackoverflow.com/questions/17806683/create-row -di-data-while-creazione-superutente che sto affrontando problema, non in grado di venire – user2086641

risposta

22

Generalmente gli oggetti del profilo utente vengono creati subito dopo la creazione dell'istanza utente. Questo è facilmente realizzato utilizzando i segnali.

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

Apparentemente l'utilizzo di segnali durante la creazione dell'utente non funzionerà per voi. Un modo per ottenere ciò che si sta tentando di fare sarebbe sostituire le chiamate a request.user.get_profile() con una funzione personalizzata. Dì get_or_create_user_profile(request). Questa funzione può provare a recuperare il profilo di un utente e quindi crearne uno al volo se uno non esiste.

Per esempio:

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

Grazie. Mi piace questa risposta, ma non mi piace modificare tutte le istanze di request.user.get_profile() nel mio codice. Non c'è un segnale che potrei collegare al profilo utente post_get (non so se esiste) – John

+0

@John: AFAIK non c'è un segnale integrato che viene inviato su 'get' (' post_get' come hai detto tu). I documenti sembrano concordare http://docs.djangoproject.com/en/dev/ref/signals/ –

+0

e come farlo attraverso il middleware? – John

3

ho trovato questa soluzione che mi piace usare a questo sito: http://www.turnkeylinux.org/blog/django-profile

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

Usando una proprietà come questa sembra più pulito di definire un nuovo metodo, ma sono d'accordo sarebbe un problema passare attraverso il codice base e modificare i riferimenti user.get_profile() a quelli user.profile.

Quindi, di nuovo, non è quello che è la funzione di ricerca e sostituzione di file globali?

+0

Generalmente il primo utente (superutente) non avrà il suo profilo creato perché è stato creato durante './manage.py startapp'. – hobbes3

+2

Il problema con questa soluzione è che colpirà il db per recuperare il profilo ogni volta che si fa riferimento a User.profile. per esempio. se fai qualcosa come: User.profile.field = "derp" quindi User.profile.save(), ricaricherà .profile dal db e perderai le tue modifiche prima di salvare. Il punto è che è un cattivo uso delle proprietà. Utilizzare invece un metodo per quella funzionalità imo – sqwerty

+0

Hmm Non penso che questo sia un cattivo uso delle proprietà. Comunque pubblicherò un miglioramento. –

3

Sulla risposta di bskinner e in risposta al commento di sqwerty, è possibile utilizzare questo:

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) 

Quindi questo sarà creare un profilo, se necessario, e poi User.profile.field = "deep"User.profile.save() opere.

1

Rivisto come di seguito. In caso contrario, verrà visualizzato "AttributeError: can not set attribute". Il tutore che assegna il permesso è facoltativo qui.

 
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

Ecco un comando di gestione sveltina che può essere utilizzato per creare profili predefiniti per tutti gli utenti che li mancano. Con questo in luogo è possibile eseguire ./manage.py missing_profiles in qualsiasi momento, o aggiungerlo a un job cron, ecc

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