web-dev-qa-db-ja.com

RelatedObjectDoesNotExist:ユーザーにユーザープロファイルがありません

したがって、次のようにフィールドscoreを使用してユーザーを拡張しました。

models.py:

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

推奨される方法 に沿っているようです。

次に、自分のビューでユーザーのuserprofileにアクセスしようとしました。

views.py:

_player = request.user.userprofile
_

これは推奨される方法にも整合しているように見えましたが、ここでエラーが発生します。

_RelatedObjectDoesNotExist
User has no userprofile.
_

userprofileを別のものに変更すると、別のエラーが発生します。

_AttributeError
'User' object has no attribute 'flowerpot'
_

次のコードを試すと:

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

コンソール出力が表示されます:

_post_test1
[]
_

[〜#〜]編集[〜#〜]
私は2人のスーパーユーザー、ユーザーを拡張する前に作成した7人のユーザー、およびユーザーを拡張した後に作成した1人のユーザー(post_test1)を持っています。


EDIT 2

ユーザーオブジェクトが作成されるたびに新しいプロファイルを作成する_post_save_ハンドラーを作成する必要があることは明らかです。

これは、私がそれを読んだときに十分に単純に思え、リンクされた page に行きました。これは、すべての信号のリストであるDjango送信のリストです。私は_post_save_そしてそれは言った:

Pre_saveに似ていますが、save()メソッドの最後に送信されます。

では、_pre_save_を検索します。

これは、モデルのsave()メソッドの最初に送信されます。

私はそれを次のように解釈しました:(_views.py_で)ユーザーを作成するときにsave()メソッドを呼び出す必要がありますが、これは今まではそうではありませんでした。 _post_save_を送信する必要があります(?)。これにより、ユーザーオブジェクトが作成されるたびに新しいプロファイルが作成されます。

だから今私は例を見始める準備ができているので、私はグーグルします:

_Django post save example_
ここ デコレータのようなものを追加することになっているようです_@receiver(post_save, ..._
ここ 複数のファイルを変更して信号定義を書き込むように思われますか?
これ は、複数のファイル(_signals.py_を含む)も意味しているようです

思った以上にたくさんあるようです。ここの誰かが私がこれをどうやってやるかを説明するか、信号がどのように機能するかについていくつかの良いリソースを見せてくれますか?

現在、_create_user_ビューは次のようになっています。

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

戻る前にnew_user.save()を呼び出す必要がありますか?はいの場合、なぜ今までうまくいったのですか?このビューのテスト中に作成したユーザーがたくさんいます。また、このあたりにpost_save.connect(create_profile, sender=User)を追加する必要がありますか?

13
MrJalapeno

最初にユーザーのuserprofileを作成する必要があります:

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

Views.pyでget_or_createを使用すると、ユーザーがいない場合に、ユーザーのユーザープロファイルが作成されます。

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

[〜#〜] update [〜#〜]:新しいユーザーが作成されるたびに自動的にユーザープロファイルを作成するには、singalsを使用します。 myapp/signals.pyでは、次のようにします。

@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

UserProfileの作成時に、Userオブジェクトの作成を強制することはありません。これを処理するには、2つの基本的な方法があります。

  1. 常にUserProfileを存在させたい場合(defaultの値をscoreに指定する場合と同様に、 _post_save_を作成しますUserオブジェクトが作成されるたびに新しいプロファイルを作成するハンドラー(ただし、保存されるたびに作成されるわけではないため、ハンドラーのcreated引数を確認してください)。

  2. ユーザーがプロファイルを持っていない可能性があると予想される場合は、アクセスするときに_UserProfile.DoesNotExist_例外をキャッチする必要があります。これを頻繁に行う場合は、何らかのヘルパー関数を作成してください。

信号の質問への回答が更新されました

また、このあたりにpost_save.connect(create_profile, sender=User)を追加する必要がありますか?

_create_profile_と呼ばれる関数を定義し、次に示すように配線する必要があります。私は通常、senderを含む_models.py_ファイルでこれを正しく行いますが、この場合、送信者は組み込みのDjangoモデルであり、すでにUserProfileを定義するファイルにそのモデルをインポートすると、その場所がその場所になります。次のようになります。

_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

上記の方法を試してもこのエラーが発生する場合は、(createsuperuserコマンドで)作成した最初のユーザーにプロファイルがないことが原因である可能性があります。

そのユーザーでログインしようとすると、このエラーが発生しました。私はそれをこのように解決しました:

-新しいユーザーを作成します。

-変更を元に戻します。 (プロフィール用に作成したコードを削除するか、コメント行にします)

-スーパーユーザーにログインします。

-新しく作成したユーザーに管理者権限を付与します。

これで、最初のユーザーを削除できます。 (プロフィールのないユーザー)

0
K.Yazoglu

まだ行っていない場合は、最初にadmin.pyでプロファイルモデルを登録します。

./manage.py createsuperuserを使用して新しいスーパーユーザーを作成します。

新しいスーパーユーザーでログインします。

管理パネルから[プロファイル]をクリックし、ユーザードロップダウンから新しいエントリとユーザーを選択して保存します。

0
Sameer Jagtap

更新された質問に答えます。モデルにはすでにsave()メソッドがあり、モデルを保存するたびに(create_user()を呼び出す場合)呼び出されます。したがって、必要なのは、ハンドラー関数を定義し、それをpost_save信号に接続することだけです。

 def create_extension(sender、instance、created、* args、** kwargs):
 if created:
#do your your 
 
 models .signals.post_save.connect(create_extension、sender = User、dispatch_uid = 'create_extension')

通常、ハンドラー関数を個別のファイルsignals.pyに入れ、models.pyの最後にconnect()ステートメントを追加します

0
Mad Wombat

シェルを使用して新しいユーザーを作成して管理ページにアクセスし、古いユーザーの管理ページからプロファイルを作成するだけです。python manage.py createsuperuser

シェルにアクセスするには、ディレクトリプロジェクト内にterminallと入力します。python manage.py Shell

0
abdelaziz barda