ChatGPT解决这个技术问题 Extra ChatGPT

Django:为什么有些模型字段会相互冲突?

我想创建一个包含 2 个指向用户的链接的对象。例如:

class GameClaim(models.Model):
    target = models.ForeignKey(User)
    claimer = models.ForeignKey(User)
    isAccepted = models.BooleanField()

但是在运行服务器时出现以下错误:

字段“目标”的访问器与相关字段“User.gameclaim_set”发生冲突。将related_name 参数添加到“目标”的定义中。

字段“claimer”的访问器与相关字段“User.gameclaim_set”发生冲突。在“claimer”的定义中添加一个related_name 参数。

您能否解释一下为什么我会收到错误以及如何修复它们?

这些错误消息非常好。 他们已经解释了如何修复它们。阅读 **[related_name in the documentation]**(docs.djangoproject.com/en/dev/ref/models/fields/#arguments) 将解释它们发生的原因。

C
Community

您有两个用户的外键。 Django 自动创建从 User 到 GameClaim 的反向关系,通常是 gameclaim_set。但是,因为您有两个 FK,所以您将有两个 gameclaim_set 属性,这显然是不可能的。所以你需要告诉 Django 为反向关系使用什么名字。

在 FK 定义中使用 related_name 属性。例如

class GameClaim(models.Model):
    target = models.ForeignKey(User, related_name='gameclaim_targets')
    claimer = models.ForeignKey(User, related_name='gameclaim_users')
    isAccepted = models.BooleanField()

很好的答案,但我不认为你成功地避免了粗鲁:P 除非你知道 django 在内部是如何工作的,否则“为什么”并不明显。
对于刚刚学习框架的人来说,这并不明显。
谢谢,错误消息对我来说也不明显,但是您对反向关系的解释非常有帮助。
仅仅因为 Clash 是一支优秀的乐队,并不能使它们成为特别具有描述性的错误消息;)
还应该提到的是,如果您不需要对所有模型使用反向关系。在某些情况下,您可能希望模型关系是一种方式。在这种情况下,您使用related_name='+'。这告诉 Django 创建单向关系并忽略反向关系。
s
salmanulfarzy

User 模型尝试创建两个具有相同名称的字段,一个用于将 User 作为 targetGameClaims,另一个用于将 User 作为 GameClaimsGameClaims 8}。这是 docs on related_name,这是 Django 让您设置属性名称的方式,这样自动生成的属性就不会发生冲突。


s
salmanulfarzy

OP 没有使用抽象基类...但如果您使用了,您会发现硬编码 FK 中的 related_name(例如 ...,related_name="myname")会导致许多此类冲突错误- 每个从基类继承的类一个。下面提供的链接包含解决方法,它很简单,但绝对不明显。

从 django 文档...

如果您在 ForeignKey 或 ManyToManyField 上使用 related_name 属性,则必须始终为该字段指定唯一的反向名称。这通常会在抽象基类中引起问题,因为此类上的字段包含在每个子类中,并且每次属性(包括相关名称)的值完全相同。

更多信息here


S
Sławomir Lenart

有时您必须在 related_name 中使用额外的格式 - 实际上,在使用继承的任何时候。

class Value(models.Model):
    value = models.DecimalField(decimal_places=2, max_digits=5)
    animal = models.ForeignKey(
        Animal, related_name="%(app_label)s_%(class)s_related")

    class Meta:
        abstract = True

class Height(Value):
    pass

class Weigth(Value):
    pass

class Length(Value):
    pass

这里没有冲突,但是related_name 定义一次,Django 将负责创建唯一的关系名称。

然后在 Value 类的孩子中,您将可以访问:

herdboard_height_related
herdboard_lenght_related
herdboard_weight_related

J
Jordan Hagan

当我将子模块作为应用程序添加到 django 项目时,我似乎偶尔会遇到这种情况,例如给定以下结构:

myapp/
myapp/module/
myapp/module/models.py

如果我将以下内容添加到 INSTALLED_APPS:

'myapp',
'myapp.module',

Django 似乎两次处理 myapp.mymodule models.py 文件并抛出上述错误。这可以通过在 INSTALLED_APPS 列表中不包括主模块来解决:

'myapp.module',

包含 myapp 而不是 myapp.module 会导致创建的所有数据库表名称不正确,因此这似乎是正确的方法。

我在寻找这个问题的解决方案时遇到了这篇文章,所以我想我会把它放在这里:)


l
lukeaus

只需添加到乔丹的答案(感谢乔丹的提示),如果您导入应用程序上方的级别然后导入应用程序,也可能会发生这种情况

myproject/ apps/ foo_app/ bar_app/

因此,如果您正在导入应用程序 foo_app 和 bar_app ,那么您可能会遇到此问题。我的应用程序 foo_app 和 bar_app 都列在 settings.INSTALLED_APPS

并且您无论如何都希望避免导入应用程序,因为那样您将相同的应用程序安装在 2 个不同的命名空间中

apps.foo_appfoo_app


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅