我想创建一个包含2个用户链接的对象。例如:
class GameClaim(models.Model):
target = models.ForeignKey(User)
claimer = models.ForeignKey(User)
isAccepted = models.BooleanField()
但运行服务器时出现以下错误:
字段'target'的访问者与相关字段'User.gameclaim_set'冲突。将related_name参数添加到'target'的定义中。
字段'claimer'的访问者与相关字段'User.gameclaim_set'发生冲突。将related_name参数添加到'claimer'的定义中。
您能否解释一下为什么我会收到错误以及如何修复错误?
答案 0 :(得分:288)
用户有两个外键。 Django自动创建一个从User回到GameClaim的反向关系,通常是gameclaim_set
。但是,因为你有两个FK,你将有两个gameclaim_set
属性,这显然是不可能的。所以你需要告诉Django反向关系使用什么名称。
使用FK定义中的related_name
属性。 e.g。
class GameClaim(models.Model):
target = models.ForeignKey(User, related_name='gameclaim_targets')
claimer = models.ForeignKey(User, related_name='gameclaim_users')
isAccepted = models.BooleanField()
答案 1 :(得分:8)
User
模型正在尝试创建两个具有相同名称的字段,一个用于GameClaims
,User
为target
,另一个用于{将GameClaims
作为User
的{1}}。这是docs on related_name
,这是Django让你设置属性名称的方式,这样自动生成的属性就不会发生冲突。
答案 2 :(得分:7)
OP没有使用抽象基类...但是如果你是,你会发现在FK中对相关名称进行硬编码(例如......,related_name =“myname”)会导致一些这些冲突错误 - 来自基类的每个继承类一个。下面提供的链接包含解决方法,这很简单,但绝对不明显。
来自django docs ......
如果您使用的是related_name ForeignKey或的属性 ManyToManyField,你必须永远 为。指定唯一的反向名称 领域。这通常会导致 抽象基类中的问题, 因为这个类的字段是 包括在每个孩子中 类,具有完全相同的值 对于属性(包括 related_name)每次。
更多信息here。
答案 3 :(得分:2)
有时你必须在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 :(得分:0)
当我将一个子模块作为应用程序添加到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 :(得分:0)
只是添加到Jordan的答案(感谢提示乔丹),如果您导入应用程序上方的级别然后导入应用程序,也会发生这种情况。
myproject/
apps/
foo_app/
bar_app/
因此,如果您要导入应用程序,foo_app和bar_app,那么您可能会遇到此问题。我在settings.INSTALLED_APPS
中列出了所有应用,foo_app和bar_app你想要避免导入应用程序,因为那时你在2个不同的命名空间中安装了相同的应用程序
apps.foo_app
和
foo_app