【问题标题】:Django: extend User model with profile onetoonefield errorsDjango:使用配置文件 onetoonefield 错误扩展用户模型
【发布时间】:2017-07-14 03:58:14
【问题描述】:

我有这个模型

from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver

from my_app.models import Teams

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    team = models.ForeignKey(Teams, on_delete=models.CASCADE)

    class Meta:
        app_label = 'my_app'

    def __str__(self):
        return self.name

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.profile.save()

然后我进入shell

from django.contrib.auth.models import User

当我输入时

user = User.objects.create_user(username='test', email='dummyemail@dum.com', password='test')

没想到

IntegrityError: NOT NULL constraint failed: my_app_profile.team_id

但是当我输入时

user = User.objects.create_user(username='test', email='dummyemail@dum.com', password='test', team='developer')

我明白了

TypeError: 'team' is an invalid keyword argument for this function

如果我输入

user = User.objects.create_user(username='test', email='dummyemail@dum.com', password='test', profile.team='developer')

我明白了

SyntaxError: keyword can't be an expression

任何帮助、提示或指导将不胜感激

【问题讨论】:

  • 您能否将您的UserTeams 模型以及您如何保存到Profile 表中。

标签: django django-models


【解决方案1】:

你不允许 team 为空,所以当你像这样创建个人资料时:

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        # Team isn't defined
        Profile.objects.create(user=instance)

你会得到一个错误。

允许团队为空(或在上面的代码中设置默认值):

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    team = models.ForeignKey(Teams, on_delete=models.CASCADE, null=True)

    class Meta:
        app_label = 'my_app'

    def __str__(self):
        return self.name

【讨论】:

  • 谢谢@Jens。是否无法将团队信息添加到 User.objects.create_user() 中的 **kwargs 中,或者我是否受限于以下方法:>>> u = User.objects.get(username='fsmith') > >> freds_department = u.employee.department
  • 否 - 您必须先单独创建用户对象,然后才能为用户创建配置文件
【解决方案2】:

当你跑步时

User.objects.create_user(username='test', email='dummyemail@dum.com', password='test')

由于post_save 信号,您会得到IntegrityError。它试图创建一个Profile 实例,但在Profile 模型中team 不能是NULLBy default, model fields have null=False

当你跑步时

user = User.objects.create_user(username='test', email='dummyemail@dum.com', 
    password='test', team='developer')

您会收到错误,因为 teamProfile 模型中的字段,而不是 User 模型中的字段。

当你跑步时

user = User.objects.create_user(username='test', email='dummyemail@dum.com', 
    password='test', profile.team='developer')

你得到错误是因为你不能使用. 来引用属性。您需要使用__ 过滤外键属性。例如,请参阅this 问题。但是,即使您使用__,它仍然会报错,因为它们在User 模型中没有名为profile 的字段。

我建议的另一件事是将两个 post_save 信号合并为一个,因为它们具有相同的发件人。

【讨论】:

    【解决方案3】:

    请参阅the documentation 关于ForeignKey.related_name。默认情况下,OneToOneField 具有关联名称以将一个模型连接到另一个模型,但 ForeignKey 没有。只要有这个选项,你就可以user.team 访问相关的模型。

    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        team = models.ForeignKey(Teams, 
                                 on_delete=models.CASCADE,
                                 related_name='team',
                                 null=True)
    

    【讨论】:

    • 他在访问相关对象时没有问题,他在创建对象时遇到了问题。
    • 我的错读错了。您初始化对象Profile,但模型等待team 的值,添加null=True。它之所以有效,是因为您允许使用空字段保存模型。
    猜你喜欢
    • 2017-06-18
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2012-03-11
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多