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

我想创建一个对象,其中包含2个链接到用户。例如:

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

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

  • 字段“ target”的访问器与相关字段“ User.gameclaim _ set”冲突。

  • 字段的访问器与相关字段‘ User.gameclaim _ set’冲突。

你能解释一下为什么我会得到这些错误以及如何修复它们吗?

40908 次浏览

User模型试图创建两个具有相同名称的字段,一个用于具有 User作为 targetGameClaims,另一个用于具有 User作为 claimerGameClaims。这是 related_name上的文件,Django 允许您设置属性的名称,这样自动生成的属性就不会发生冲突。

您有两个用户的外键。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()

OP 没有使用抽象基类... ... 但是如果你使用抽象基类的话,你会发现在 FK 中硬编码了 related _ name (例如... ,related _ name = “ myname”)会导致许多这样的冲突错误——从基类继承的每个类都会出现一个冲突错误。下面提供的链接包含解决方案,这很简单,但绝对不明显。

来自姜戈的文件..。

如果您使用的是 related _ name 在 ForeignKey 或 你必须永远 类指定唯一的反向名称 字段。这通常会导致 抽象基类中的问题, 因为这个类中的字段是 包括在每个孩子里 类,具有完全相同的值 属性(包括 名称)。

更多信息 给你

当我将子模块作为应用程序添加到 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会导致所有数据库表的创建名称都不正确,因此这似乎是正确的方法。

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

只是添加到乔丹的答案(感谢乔丹的提示) ,它也可以发生,如果你导入的水平以上的应用程序,然后导入应用程序,例如。

我的计划/ 应用程式/ Foo _ app/ Bar _ app/

因此,如果您导入应用程序,foo _ app 和 bar _ app,那么您可能会遇到这个问题。我有应用程序,foo _ app 和 bar _ app 都列在 setings.INSTALLED _ APPS 中

而且无论如何都要避免导入应用程序,因为这样就会在两个不同的名称空间中安装相同的应用程序

apps.foo_app 还有 foo_app

有时在 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

这里没有冲突,但是仅定义了一次 relevant _ name,并且 Django 将负责创建惟一的关系名称。

然后在 Value 类的子类中,你可以访问:

herdboard_height_related
herdboard_lenght_related
herdboard_weight_related