web-dev-qa-db-fra.com

RelatedObjectDoesNotExist: l'utilisateur n'a pas de profil utilisateur

J'ai donc étendu mon utilisateur avec le champ score comme ceci:

models.py:

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    score = models.IntegerField(default=0);

qui semblait aller dans le sens de la manière recommandée .

Ensuite, j'ai essayé d'accéder au userprofile de l'utilisateur dans mes vues:

views.py:

player = request.user.userprofile

qui semblait également correspondre à la méthode recommandée, mais c'est là que je reçois mon erreur:

RelatedObjectDoesNotExist
User has no userprofile.

Si je change userprofile en quelque chose d'autre, j'obtiens une autre erreur:

AttributeError
'User' object has no attribute 'flowerpot'

Lorsque j'essaie le code suivant:

print request.user
print UserProfile.objects.all()

J'obtiens la sortie console:

post_test1
[]

[~ # ~] modifier [~ # ~]
J'ai deux superutilisateurs, sept utilisateurs que j'ai créés avant d'étendre l'utilisateur et un utilisateur (post_test1) que j'ai créé après avoir étendu l'utilisateur.


EDIT 2

Il semble clair que ce dont j'ai besoin est de créer un gestionnaire post_save Qui crée un nouveau profil chaque fois que l'objet User est créé.

Cela semblait assez simple quand je l'ai lu, je suis allé à la page à laquelle était lié, qui était une liste de tous les signaux Django envoie. J'ai recherché post_save Et il a dit:

Comme pre_save, mais envoyé à la fin de la méthode save ().

Très bien, donc je recherche pre_save Et ça dit:

Il est envoyé au début de la méthode save () d'un modèle.

Je l'ai interprété comme ceci: lorsque je crée mon utilisateur (dans mon views.py), La méthode save() doit être appelée, ce qui n'a pas été le cas jusqu'à présent, et après cela un post_save doit être envoyé (?), ce qui créera un nouveau profil à chaque création de l'objet Utilisateur!

Alors maintenant, je suis prêt à commencer à regarder des exemples, alors je google:

Django post save example
Ici on dirait que je suis censé ajouter quelque chose qui ressemble à un décorateur @receiver(post_save, ...
Ici on dirait que je suis censé modifier plusieurs fichiers et écrire une définition de signal?
Celui-ci semble également impliquer plusieurs fichiers (y compris un signals.py)

Il semble qu'il y ait beaucoup plus que je ne le pensais au départ. Quelqu'un ici pourrait-il expliquer comment je dois procéder ou me montrer de bonnes ressources sur le fonctionnement des signaux?

En ce moment, ma vue create_user Ressemble à ceci:

def create_user(request):
    if request.method == "POST":
        form = UserCreationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data["username"]
            password = form.cleaned_data["password1"]
            new_user = User.objects.create_user(username=username, password=password)
            return redirect('play')
    else:
        form = UserCreationForm()

    return render(request, 'antonymapp/create_user.html', {'form': form})

Dois-je appeler new_user.save() avant de revenir? Si oui, pourquoi cela a-t-il fonctionné jusqu'à présent? J'ai un groupe d'utilisateurs que j'ai créés en testant cette vue. Il semble également quelque part ici post_save.connect(create_profile, sender=User) devrait être ajouté?

13
MrJalapeno

Vous devez d'abord créer un userprofile pour l'utilisateur:

profile = UserProfile.objects.create(user=request.user)

Dans votre views.py, vous pouvez utiliser get_or_create pour qu'un profil utilisateur soit créé pour un utilisateur s'il n'en a pas.

player, created = UserProfile.objects.get_or_create(user=request.user)

UPDATE : Pour créer automatiquement des profils utilisateur chaque fois qu'un nouvel utilisateur est créé, utilisez des singals. Dans myapp/signals.py faites quelque chose comme ceci:

@receiver(post_save, sender=User, dispatch_uid='save_new_user_profile')
def save_profile(sender, instance, created, **kwargs):
    user = instance
    if created:
        profile = UserProfile(user=user)
        profile.save()
12
v1k45

Rien dans ce que vous avez fait ne force la création d'un objet UserProfile lorsqu'un User est créé. Il existe deux méthodes de base pour gérer cela:

  1. Si vous voulez toujours qu'un UserProfile existe (ce qui semble être le cas lorsque vous donnez une valeur de default à score, créez un post_save gestionnaire qui crée un nouveau profil chaque fois que l'objet User est créé (mais pas à chaque fois qu'il est enregistré, assurez-vous donc de vérifier l'argument created dans le gestionnaire).

  2. S'il est prévu qu'un utilisateur ne dispose pas d'un profil, vous devez intercepter l'exception UserProfile.DoesNotExist Lorsque vous essayez d'y accéder. Si vous le faites fréquemment, créez une sorte de fonction d'assistance.

MISE À JOUR DE LA RÉPONSE À LA QUESTION DE SIGNAL

Il semble également quelque part ici post_save.connect(create_profile, sender=User) devrait être ajouté?

Vous devez définir une fonction appelée create_profile, Puis la câbler comme vous l'avez montré. Je le fais généralement dans le fichier models.py Qui inclut le sender mais dans ce cas où l'expéditeur est un modèle intégré Django et vous êtes déjà en train d'importer ce modèle dans le fichier où vous définissez votre UserProfile c'est l'endroit où le faire. Cela ressemblerait à quelque chose comme:

def create_profile(sender, instance, created, *args, **kwargs):
    # ignore if this is an existing User
    if not created:
        return
    UserProfile.objects.create(user=instance)
post_save.connect(create_profile, sender=User)
1
Tom

Si vous obtenez cette erreur même si vous avez essayé les suggestions ci-dessus, cela peut être dû au fait que le premier utilisateur que vous avez créé (avec la commande createuperuser) n'a pas de profil.

J'obtenais cette erreur lorsque j'ai essayé de me connecter avec cet utilisateur. Je l'ai résolu de cette façon:

-Créer un nouvel utilisateur.

- Annulez les changements. (Effacez le code que vous avez écrit pour Profile ou faites-en des lignes de commentaires)

- Connectez-vous à votre superutilisateur.

-Donner l'autorisation d'administrateur à l'utilisateur nouvellement créé.

Vous pouvez maintenant supprimer le premier utilisateur. (L'utilisateur sans profil)

0
K.Yazoglu

Enregistrez d'abord le modèle de profil dans admin.py si ce n'est déjà fait.

Créez un nouveau superutilisateur à l'aide de ./manage.py createuperuser.

Connectez-vous avec le nouveau superutilisateur.

Dans le panneau d'administration, cliquez sur Profil et ajoutez une nouvelle entrée et sélectionnez l'utilisateur dans la liste déroulante des utilisateurs et enregistrez.

0
Sameer Jagtap

Répondre à votre question mise à jour. Il existe déjà une méthode save () dans les modèles et elle est appelée à chaque fois que vous enregistrez un modèle (dans votre cas, lorsque vous appelez create_user ()). Il vous suffit donc de définir une fonction de gestionnaire et de la connecter au signal post_save.

 def create_extension (expéditeur, instance, créé, * args, ** kwargs): 
 si créé: 
 # faites votre truc 
 
 modèles .signals.post_save.connect (create_extension, sender = User, dispatch_uid = 'create_extension') 

Je place généralement les fonctions de gestionnaire dans un fichier séparé signaux.py et ajoute des instructions connect () à la fin de models.py

0
Mad Wombat

Essayez simplement de créer un nouvel utilisateur à l'aide de Shell pour accéder à la page d'administration, puis créez un profil à partir de la page d'administration pour l'ancien utilisateur: python manage.py createuperuser

Pour accéder à Shell, dans votre projet d'annuaire, entrez le type de terminall: python manage.py Shell

0
abdelaziz barda