题
我在Django中有一个扩展的用户填充模型:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
#other things in that profile
和一个信号。
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匹配查询”错误,这意味着数据库条目不存在。
我应该说我使用Django-Registration,该注册提供了user_registered信号。
重要的应用程序的结构是,我有一个称为“用户”的应用程序,我有:models.py,signals.py,urls.py and views.py(以及其他一些不重要的事情)。用户填充类是在Models.py中定义的。
更新: :我将Signal.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)
但是现在我得到了一个“ IntegrityError”:
“列User_id不是唯一的”
编辑2:
我找到了。看来我以某种方式对信号进行了两次注册。在这里描述了解决方案: http://code.djangoproject.com/wiki/signals#helppost_saveseemstobeemtobeemittedtwiceforeachsave
我不得不添加一个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/
这对我有帮助:prientar_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)