Django 创建扩展用户配置文件

Django 创建扩展用户配置文件,django,django-registration,Django,Django Registration,我在django中有一个扩展的UserProfile模型: 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.c

我在django中有一个扩展的UserProfile模型:

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)
我确保通过在我的
\uuuu init\uuuuuuuy.py
中注册该信号:

import signals
这应该为每个注册的用户创建一个新的用户配置文件,对吗?但事实并非如此。当我尝试登录时,总是出现“UserProfile matching query not Existence”错误,这意味着数据库条目不存在

我应该说我使用django注册,它提供用户注册信号

这方面重要应用程序的结构是,我有一个名为“用户”的应用程序,我有:models.py、signals.py、url.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)
但现在我得到了一个“完整的错误”:

“列用户\u id不唯一”

编辑2:

我找到了。看起来不知怎么的我注册了两次信号。此处介绍了解决此问题的方法:

我必须添加一个调度uid,现在我的signals.py看起来像这样并且正在工作:

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")

调用
profile.setUser()
时,我认为您希望传递
instance
而不是
sender
作为参数


从中,
sender
指的是
User
类<代码>实例是已注册的实际用户对象。

您可以在用户上使用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

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

ref:

这对我有帮助:primary\u 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")

根据我最近的研究,创建一个单独的文件,例如singals.py,是行不通的

您最好直接将models.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的最新版本

来自django.dispatch导入接收方
从django.db.models.signals导入后保存
从django.conf导入设置
从模型导入用户配置文件
@接收方(保存后,发送方=设置。验证用户模型)
def create_user_配置文件(发送方,实例=None,created=False,**kwargs):
如果创建:
UserProfile.objects.create(用户=实例)

能否将结构发布到django应用程序中。我很好奇你的代码中有几行代码,比如
profile=user.models.UserProfile()
-你有一个名为“user”的模块吗?UserProfile()位于何处。是users,我不知道这个输入错误是如何出现的,但问题是相同的。我想知道为什么python没有为拼写错误的路径抛出错误。感谢这个解决方案,我是django的新手,我不知道如何保存关于用户配置文件的其他数据。我知道您只是将用户保存在model UserProfile中,但是如何从注册表中保存其他人的数据(使用您的signals.py)?我认为,Thansk(抱歉用英语)必须是“profile.setUser(user)”。但是我得到了“列用户id不是唯一的”。对此有什么想法吗?我在我的答案中添加了另一个可能的解决方案,请检查。我得到“列用户id不唯一”,您能给我看一下您的用户配置文件模型吗?也许我把外键弄错了,让它起作用了。如果您对解决方案感兴趣,请查看我的第一篇文章。@Agos在
create\u profile
中描述如何获取
stuff
thing
的值将非常有帮助。primary\u key=True意味着null=False和unique=True。我认为(对于2018年,django>=1.11)应该始终是:
sender=get\u user\u model()。是否应该将
UserProfile.objects.create(user=instance)
改为
UserProfile.objects.create(user=instance,**kwargs)
?@theeast coast-west-nope。
**kwargs
与信号本身相关,它不包含创建配置文件时要使用的任何数据。事实上,您只想创建一个干净的UserProfile模型,而不是以任何方式对其进行更改。是否有一个源代码可以让我了解使用信号创建相关对象(例如本例中的
UserProfile
)与使用模型管理器的区别?他们的方法和最佳实践的优缺点是什么?非常感谢。
# 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")