问题:Django:为什么某些模型字段会相互冲突?
我想创建一个包含2个指向用户的链接的对象。例如:
class GameClaim(models.Model):
target = models.ForeignKey(User)
claimer = models.ForeignKey(User)
isAccepted = models.BooleanField()
但是运行服务器时出现以下错误:
字段“目标”的访问器与相关字段“ User.gameclaim_set”冲突。在’target’的定义中添加related_name参数。
字段“ claimer”的访问器与相关字段“ User.gameclaim_set”冲突。在“ claimer”的定义中添加一个related_name参数。
您能否解释为什么我会收到错误以及如何解决这些错误?
回答 0
您有两个用户外键。Django自动创建一个从User到GameClaim的反向关系,通常是gameclaim_set
。但是,由于您有两个FK,因此将具有两个gameclaim_set
属性,这显然是不可能的。因此,您需要告诉Django用于反向关系的名称。
使用related_name
FK定义中的属性。例如
class GameClaim(models.Model):
target = models.ForeignKey(User, related_name='gameclaim_targets')
claimer = models.ForeignKey(User, related_name='gameclaim_users')
isAccepted = models.BooleanField()
回答 1
该User
模型试图创建具有相同名称的两个领域,一个是GameClaims
说有User
作为target
,而另一个用于GameClaims
该有User
作为claimer
。这是上的文档related_name
,这是Django允许您设置属性名称的方法,以便自动生成的属性不会冲突。
回答 2
OP没有使用抽象基类…但是,如果您使用的是,您会发现在FK中硬编码related_name(例如…,related_name =“ myname”)会导致许多此类冲突错误-从基类继承的每个类一个。下面提供的链接包含解决方法,这很简单,但绝对不明显。
从Django文档…
如果在ForeignKey或ManyToManyField上使用related_name属性,则必须始终为该字段指定唯一的反向名称。这通常会在抽象基类中引起问题,因为此类的字段包含在每个子类中,并且每次属性(包括related_name)的值都完全相同。
更多信息在这里。
回答 3
有时,您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
回答 4
当我将子模块作为应用程序添加到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
会导致所有数据库表都使用不正确的名称创建,因此这似乎是正确的方法。
我在寻找此问题的解决方案时遇到了这篇文章,所以我想把它放在这里:)
回答 5
只是添加约旦的答案(感谢约旦的提示),如果您在应用程序上方导入级别,然后导入应用程序,则也可能发生这种情况,例如
myproject/
apps/
foo_app/
bar_app/
因此,如果要导入应用程序foo_app和bar_app,则可能会遇到此问题。我的应用程序foo_app和bar_app都列在设置中。INSTALLED_APPS
而且您还是想避免导入应用程序,因为那样您会将相同的应用程序安装在2个不同的命名空间中
apps.foo_app
和
foo_app