在Django中,同一个模型有多个多对多关系

时间:2022-10-04 16:30:13

Given the following model with two many-to-many relations:

给出了具有多对多关系的如下模型:

class Child(models.Model):
    name = models.CharField(max_length=80)

class Foo(models.Model):
    bar = models.ManyToManyField(Child)
    baz = models.ManyToManyField(Child)

This gives the error:

这就给了错误:

accounts.foo: Accessor for m2m field 'bar' *es with related m2m field 'Child.foo_set'. Add a related_name argument to the definition for 'bar'.
accounts.foo: Accessor for m2m field 'baz' *es with related m2m field 'Child.foo_set'. Add a related_name argument to the definition for 'baz'.

Fine; I don't need the backwards relation. According to the Django docs for related_name (which is only under ForeignKey as far as I can see), I can set related_name="+" and backward relations won't be created:

罚款;我不需要反向关系。根据Django关于related_name的文档(据我所知只有在ForeignKey下),我可以设置related_name="+",并且不会创建反向关系:

class Child(models.Model):
    name = models.CharField(max_length=80)

class Foo(models.Model):
    bar = models.ManyToManyField(Child, related_name="+")
    baz = models.ManyToManyField(Child, related_name="+")

This doesn't work though:

不过这并不工作:

accounts.foo: Accessor for m2m field 'bar' *es with related m2m field 'Child.+'. Add a related_name argument to the definition for 'bar'.
accounts.foo: Reverse query name for m2m field 'bar' *es with related m2m field 'Child.+'. Add a related_name argument to the definition for 'bar'.
accounts.foo: Accessor for m2m field 'baz' *es with related m2m field 'Child.+'. Add a related_name argument to the definition for 'baz'.
accounts.foo: Reverse query name for m2m field 'baz' *es with related m2m field 'Child.+'. Add a related_name argument to the definition for 'baz'.

What do I need to do to avoid creating reverse relations?

我需要做什么来避免产生反向关系?

2 个解决方案

#1


28  

I think you need to just give the two fields different related_names:

我认为你需要给两个字段提供不同的related_names:

class Child(models.Model):
  name = models.CharField(max_length=80)

class Foo(models.Model):
  bar = models.ManyToManyField(Child, related_name="bar")
  baz = models.ManyToManyField(Child, related_name="baz")

If you don't give a related name, then it's trying to create the same accessor name (foo_set) twice on the Child model. If you give the same related name, it's again going to try to create the same accessor twice, so you need to give unique related names. With the above code to define your models, then given a Child instance c, you can access related Foo objects with c.bar.all() and c.baz.all().

如果您没有给出相关的名称,那么它将尝试在子模型上两次创建相同的访问器名称(foo_set)。如果您提供相同的相关名称,它将再次尝试创建相同的访问器两次,因此您需要提供唯一的相关名称。使用上面的代码定义模型,然后给定一个子实例c,您可以使用c.bar.all()和c.baz.all()访问相关的Foo对象。

If you don't want the backwards relations, then append a + to each of the (unique) related names:

如果您不想要反向关系,那么将a +附加到每个(唯一的)相关名称:

class Foo(models.Model):
  bar = models.ManyToManyField(Child, related_name="bar+")
  baz = models.ManyToManyField(Child, related_name="baz+")

#2


12  

You haven't read Django's documentation carefully enough. Here it says:

您还没有仔细阅读Django的文档。这表示:

If you have more than one ManyToManyField pointing to the same model and want to suppress the backwards relations, set each related_name to a unique value ending with '+'.

如果您有多个ManyToManyField指向相同的模型,并且想要抑制反向关系,请将每个related_name设置为以“+”结尾的唯一值。

The related_name attributes have to be unique, not the same.

related_name属性必须是唯一的,而不是相同的。

#1


28  

I think you need to just give the two fields different related_names:

我认为你需要给两个字段提供不同的related_names:

class Child(models.Model):
  name = models.CharField(max_length=80)

class Foo(models.Model):
  bar = models.ManyToManyField(Child, related_name="bar")
  baz = models.ManyToManyField(Child, related_name="baz")

If you don't give a related name, then it's trying to create the same accessor name (foo_set) twice on the Child model. If you give the same related name, it's again going to try to create the same accessor twice, so you need to give unique related names. With the above code to define your models, then given a Child instance c, you can access related Foo objects with c.bar.all() and c.baz.all().

如果您没有给出相关的名称,那么它将尝试在子模型上两次创建相同的访问器名称(foo_set)。如果您提供相同的相关名称,它将再次尝试创建相同的访问器两次,因此您需要提供唯一的相关名称。使用上面的代码定义模型,然后给定一个子实例c,您可以使用c.bar.all()和c.baz.all()访问相关的Foo对象。

If you don't want the backwards relations, then append a + to each of the (unique) related names:

如果您不想要反向关系,那么将a +附加到每个(唯一的)相关名称:

class Foo(models.Model):
  bar = models.ManyToManyField(Child, related_name="bar+")
  baz = models.ManyToManyField(Child, related_name="baz+")

#2


12  

You haven't read Django's documentation carefully enough. Here it says:

您还没有仔细阅读Django的文档。这表示:

If you have more than one ManyToManyField pointing to the same model and want to suppress the backwards relations, set each related_name to a unique value ending with '+'.

如果您有多个ManyToManyField指向相同的模型,并且想要抑制反向关系,请将每个related_name设置为以“+”结尾的唯一值。

The related_name attributes have to be unique, not the same.

related_name属性必须是唯一的,而不是相同的。