我想创建一个包含 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) 将解释它们发生的原因。
您有两个用户的外键。 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()
User
模型尝试创建两个具有相同名称的字段,一个用于将 User
作为 target
的 GameClaims
,另一个用于将 User
作为 GameClaims
的 GameClaims
8}。这是 docs on related_name
,这是 Django 让您设置属性名称的方式,这样自动生成的属性就不会发生冲突。
OP 没有使用抽象基类...但如果您使用了,您会发现硬编码 FK 中的 related_name(例如 ...,related_name="myname")会导致许多此类冲突错误- 每个从基类继承的类一个。下面提供的链接包含解决方法,它很简单,但绝对不明显。
从 django 文档...
如果您在 ForeignKey 或 ManyToManyField 上使用 related_name 属性,则必须始终为该字段指定唯一的反向名称。这通常会在抽象基类中引起问题,因为此类上的字段包含在每个子类中,并且每次属性(包括相关名称)的值完全相同。
更多信息here。
有时您必须在 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
当我将子模块作为应用程序添加到 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
会导致创建的所有数据库表名称不正确,因此这似乎是正确的方法。
我在寻找这个问题的解决方案时遇到了这篇文章,所以我想我会把它放在这里:)
只需添加到乔丹的答案(感谢乔丹的提示),如果您导入应用程序上方的级别然后导入应用程序,也可能会发生这种情况
myproject/ apps/ foo_app/ bar_app/
因此,如果您正在导入应用程序 foo_app 和 bar_app ,那么您可能会遇到此问题。我的应用程序 foo_app 和 bar_app 都列在 settings.INSTALLED_APPS
并且您无论如何都希望避免导入应用程序,因为那样您将相同的应用程序安装在 2 个不同的命名空间中
apps.foo_app
和 foo_app