したがって、次のようにフィールド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)
を追加する必要がありますか?
最初にユーザーの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()
UserProfile
の作成時に、User
オブジェクトの作成を強制することはありません。これを処理するには、2つの基本的な方法があります。
常にUserProfile
を存在させたい場合(default
の値をscore
に指定する場合と同様に、 _post_save
_を作成しますUser
オブジェクトが作成されるたびに新しいプロファイルを作成するハンドラー(ただし、保存されるたびに作成されるわけではないため、ハンドラーのcreated
引数を確認してください)。
ユーザーがプロファイルを持っていない可能性があると予想される場合は、アクセスするときに_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)
_
上記の方法を試してもこのエラーが発生する場合は、(createsuperuserコマンドで)作成した最初のユーザーにプロファイルがないことが原因である可能性があります。
そのユーザーでログインしようとすると、このエラーが発生しました。私はそれをこのように解決しました:
-新しいユーザーを作成します。
-変更を元に戻します。 (プロフィール用に作成したコードを削除するか、コメント行にします)
-スーパーユーザーにログインします。
-新しく作成したユーザーに管理者権限を付与します。
これで、最初のユーザーを削除できます。 (プロフィールのないユーザー)
まだ行っていない場合は、最初にadmin.pyでプロファイルモデルを登録します。
./manage.py createsuperuserを使用して新しいスーパーユーザーを作成します。
新しいスーパーユーザーでログインします。
管理パネルから[プロファイル]をクリックし、ユーザードロップダウンから新しいエントリとユーザーを選択して保存します。
更新された質問に答えます。モデルにはすでに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()ステートメントを追加します
シェルを使用して新しいユーザーを作成して管理ページにアクセスし、古いユーザーの管理ページからプロファイルを作成するだけです。python manage.py createsuperuser
シェルにアクセスするには、ディレクトリプロジェクト内にterminallと入力します。python manage.py Shell