Relations multiples avec le même modèle à Django

étant donné le modèle suivant avec deux relations de plusieurs à plusieurs:

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

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

Ce qui donne l'erreur:

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

bien; je n'ai pas besoin de la relation à l'envers. selon les Docs de Django pour related_name (qui est seulement sous ForeignKey aussi loin que je puisse voir), je peux mettre related_name="+" et en arrière, les relations ne seront pas créés:

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="+")

Cela ne fonctionne pas bien:

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

Que dois-je faire pour éviter de créer inverse les relations?

23
demandé sur Wilfred Hughes 2012-12-17 21:26:15

2 réponses

je pense que vous avez juste besoin de donner les deux champs différents 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")

si vous ne donnez pas un nom apparenté, alors il essaie de créer le même nom d'accesseur (foo_set) deux fois sur l' Child modèle. Si vous donnez le même nom apparenté, il va de nouveau essayer de créer le même accesseur deux fois, donc vous devez donner des noms apparentés uniques. Avec le code ci-dessus pour définir vos modèles, puis Child exemple c, vous pouvez accéder connexes Foo objets avec c.bar.all() et c.baz.all().

si vous ne voulez pas les relations à l'envers, alors ajoutez un + à chacun de (unique) des noms relatifs à:

class Foo(models.Model):
  bar = models.ManyToManyField(Child, related_name="bar+")
  baz = models.ManyToManyField(Child, related_name="baz+")
30
répondu Emily 2012-12-17 17:54:04

Vous n'avez pas lu assez attentivement la documentation de Django. Ici il dit:

si vous avez plus d'un ManyToManyField pointant vers le même modèle et que vous voulez supprimer les relations à l'envers, définissez chaque nom_related à un valeur unique se terminant par un '+'.

related_name les attributs doivent être uniques, pas identiques.

12
répondu pemistahl 2012-12-17 17:44:50