2010-09-14 4 views
18

J'utilise request.user.get_profile() dans un certain nombre d'endroits dans mon code. Cependant, tous les utilisateurs n'ont pas un profil utilisateur assosié à leur compte. Est-il possible de créer un profil utilisateur automatiquement lorsque j'appelle le request.user.get_profile() s'il n'en a pas un sans avoir à changer chacun de mes request.user.get_profile() appels. Peut-être en utilisant des signaux ou quelque chose. Le problème que j'ai est que j'utilise un identifiant de connexion unique, donc si quelqu'un se connecte sur un autre système puis va sur mon site, il est connecté mais ne crée pas de profil utilisateur (je crée un utilisateur profil quand ils se connectent).Django créer userprofile si n'existe pas

+0

pouvez-vous s'il vous plaît vérifier cette question SO http://stackoverflow.com/questions/17806683/create-row -of-date-while-creation-superuser auquel je suis confronté problème, pas capable de venir – user2086641

Répondre

22

Généralement, les objets de profil utilisateur sont créés juste après la création de l'instance utilisateur. Ceci est facilement accompli en utilisant des signaux. Apparemment, l'utilisation de signaux au moment de la création de l'utilisateur ne fonctionnera pas pour vous. Une façon d'accomplir ce que vous essayez de faire serait de remplacer les appels à request.user.get_profile() avec une fonction personnalisée. Dites get_or_create_user_profile(request). Cette fonction peut essayer de récupérer le profil d'un utilisateur et en créer un à la volée s'il n'en existe pas.

Pour exemple:

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

Merci. J'aime cette réponse mais je ne voulais pas changer toutes les instances de request.user.get_profile() dans mon code. N'y a-t-il pas un signal que je pourrais attacher au UserProfile post_get (je ne sais pas si cela existe) – John

+0

@John: AFAIK il n'y a pas de signal intégré qui est envoyé sur 'get' (' post_get' comme vous l'avez dit). Les docs semblent être d'accord http://docs.djangoproject.com/en/dev/ref/signals/ –

+0

et pourquoi ne pas le faire via le middleware? – John

3

J'ai trouvé cette solution que je préfère utiliser sur ce site: http://www.turnkeylinux.org/blog/django-profile

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

En utilisant une propriété comme cela semble plus propre que la définition d'une nouvelle méthode, mais je suis d'accord ce serait difficile de passer en revue votre base de code et de changer user.get_profile() références à user.profile.

Là encore, n'est-ce pas ce que votre fonction globale de recherche et de remplacement de fichiers est destinée?

+0

Habituellement le premier utilisateur (superutilisateur) n'aura pas son profil créé car il a été créé pendant './manage.py startapp'. – hobbes3

+2

Problème avec cette solution est qu'il va frapper la base de données pour récupérer le profil chaque fois que vous référencez User.profile. par exemple. Si vous faites quelque chose comme: User.profile.field = "derp" puis User.profile.save(), il rechargera .profile à partir de la base de données et perdra vos modifications avant d'enregistrer. Point étant que c'est une mauvaise utilisation des propriétés. Utilisez une méthode à la place pour cette fonctionnalité. – sqwerty

+0

Hmm Je ne pense pas que ce soit une mauvaise utilisation des propriétés. Je posterai une amélioration cependant. –

3

Miser sur la réponse de bskinner et en réponse au commentaire de sqwerty, vous pouvez utiliser ceci:

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) 

Donc cela va créer un profil si nécessaire, et puis User.profile.field = "deep"User.profile.save() œuvres.

1

Révisée comme ci-dessous. Sinon, "AttributeError: impossible de définir l'attribut" sera affiché. La permission d'assignation du gardien est facultative ici.

 
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

Voici une commande de gestion rapide qui peut être utilisée pour créer des profils par défaut pour les utilisateurs qui en sont dépourvus. Avec cela en place, vous pouvez exécuter ./manage.py missing_profiles à tout moment, ou l'ajouter à une tâche cron, 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)) 
Questions connexes