質問
私はdjangoに拡張ユーザープロファイルモデルを持っています:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
#other things in that profile
とsignals.py:
from registration.signals import user_registered
from models import UserProfile
from django.contrib.auth.models import User
def createUserProfile(sender, instance, **kwargs):
profile = users.models.UserProfile()
profile.setUser(sender)
profile.save()
user_registered.connect(createUserProfile, sender=User)
私はこれを自分に持っていることによって信号が登録されることを確認します __init__.py
:
import signals
それで、それは私が登録するすべてのユーザーの新しいユーザープロファイルを作成するはずですよね?しかし、そうではありません。ログインしようとすると、「userprofileマッチングクエリは存在しません」エラーを常に取得します。つまり、データベースエントリがありません。
user_registered信号を提供するdjango-registrationを使用していると言う必要があります。
これの重要なアプリの構造は、「ユーザー」と呼ばれる1つのアプリケーションがあることです。モデル、signals.py、urls.py、views.py(およびここでは重要ではないものがあります。 )。 userprofileクラスは、models.pyで定義されています。
アップデート: :signals.pyを次のように変更しました。
from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User
def create_profile(sender, **kw):
user = kw["instance"]
if kw["created"]:
profile = UserProfile()
profile.user = user
profile.save()
post_save.connect(create_profile, sender=User)
しかし今、私は「誠実な」を手に入れます:
「列user_idは一意ではありません」
編集2:
見つけた。どういうわけか私は信号を2回登録したようです。これの回避策はここで説明されています: http://code.djangoproject.com/wiki/signals#helppost_saveseemstobeemittwiceforeachsave
Dispatch_uidを追加する必要がありました。
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from models import UserProfile
from django.db import models
def create_profile(sender, **kw):
user = kw["instance"]
if kw["created"]:
profile = UserProfile(user=user)
profile.save()
post_save.connect(create_profile, sender=User, dispatch_uid="users-profilecreation-signal")
解決
ユーザーのpost_saveを使用して実装できます。
from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
profile = users.models.UserProfile()
profile.setUser(sender)
profile.save()
post_save.connect(create_profile, sender=User)
編集:
テストされ、機能する別の可能なソリューション(私は自分のサイトで使用しています):
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
up = UserProfile(user=user, stuff=1, thing=2)
up.save()
post_save.connect(create_profile, sender=User)
他のヒント
代わりに各ユーザーに最初にアクセスするときに、拡張プロファイルを作成することができます。
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
additional_info_field = models.CharField(max_length=50)
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
次に、使用します
from django.contrib.auth.models import User
user = User.objects.get(pk=1)
user.profile.additional_info_field
参照: http://www.codekoala.com/blog/2009/quick-django-tip-user-profiles/
これは私を助けました:Primary_key = true
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True, primary_key=True, related_name="user")
phone = models.CharField(('phone'),max_length=30, blank=False, null=True)
user_building = models.ManyToManyField(Building, blank=True)
added_by = models.ForeignKey(User, blank=True, null=True, related_name="added")
あなたが電話するとき profile.setUser()
, 、あなたは合格したいと思います instance
それよりも sender
パラメーターとして。
から user_registered信号のドキュメント, sender
を参照 User
クラス; instance
登録された実際のユーザーオブジェクトです。
私の最新の調査によると、たとえばSingals.pyなどの別のファイルを作成するとは機能しません。
モデルの「create_profile」を「post_save」に直接接続する方が良い場合は、このコードは別のファイルにあり、誰もインポートしないため、このコードは実行されません。
あなたの参照のための私の最終コード:
# models.py
# Here goes the definition of class UserProfile.
class UserProfile(models.Model):
...
# Use signal to automatically create user profile on user creation.
# Another implementation:
# def create_user_profile(sender, **kwargs):
# user = kwargs["instance"]
# if kwargs["created"]:
# ...
def create_user_profile(sender, instance, created, **kwargs):
"""
:param sender: Class User.
:param instance: The user instance.
"""
if created:
# Seems the following also works:
# UserProfile.objects.create(user=instance)
# TODO: Which is correct or better?
profile = UserProfile(user=instance)
profile.save()
post_save.connect(create_user_profile,
sender=User,
dispatch_uid="users-profilecreation-signal")
2018年の更新:
この質問は多くの意見を集めています。多分それは更新の時です。
これは、最新のDjangoの最新バージョンです。
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.conf import settings
from models import UserProfile
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance=None, created=False, **kwargs):
if created:
UserProfile.objects.create(user=instance)