Django ManyToMany field through with extra fields does not show on both relations

南笙酒味 提交于 2021-02-09 17:59:47

问题


I have a class Assembly

class Assembly(models.Model):

    room = models.ForeignKey("Room", related_name="assemblies")
    name = models.CharField(max_length=200)
    number = models.IntegerField()
    position = models.CharField(max_length=200, blank=True)
    components = models.ManyToManyField("material.Component", through="m2m_Assembly_Components")
    connections = models.ManyToManyField("Assembly", through="Connection")
    category = models.ForeignKey("Category", default=0)
    notes = models.TextField(blank=True)

that has a ManyToMany Realtionship between instances of itself (connections). I use an intermediary table Connection so that i can have additional fields for a connection between two instances of an Assembly.

class Connection(models.Model):

    source = models.ForeignKey("Assembly", related_name="source_assembly", null=True)
    destination = models.ForeignKey("Assembly", related_name="destination_assembly", null=True)
    length = models.IntegerField(null=True, blank=True)

If I have two Assemblies, lets say A and B, and I connect them by defining a new Connection with A as source and B as destination, I get B as A's connections (A.connections.all()), but I don't get A as B's connections.

If I don't use an intermediary table, just a models.ManyToManyField("Assembly") I get A as B's connections and B as A's connections.

What is my problem here?


回答1:


I think you need to specify the through_fields argument to your ManyToManyField.

When Django autogenerates your through model, it knows which of the two ForeignKeys in it corresponds to the "local" end of the relationship, and which is the "remote" end. However, when you specify a custom intermediary model, this makes it more difficult. It is possible that Django just takes the first ForeignKey in the intermediary model pointing to the right target model, which in both cases happens to be source here (although I'm not sure this is really the case, and if it is, it might be a bug).

Try to see if using through_fields=('source', 'destination') helps.




回答2:


Following up on the @koniiiik's answer regarding through_fields:

Recursive relationships using an intermediary model are always defined as non-symmetrical – that is, with symmetrical=False – therefore, there is the concept of a “source” and a “target”. In that case 'field1' will be treated as the “source” of the relationship and 'field2' as the “target”.

and, in your case it is source and destination.

Since you are using an intermediary model Connection, the relationship is not symmetrical anymore. Therefore, A.connections.all() and B.connections.all() will return different results.

A.connections.all() #all assemblies where A is source
B.connections.all() # all assemblies where B is source

if you add a connection:

Connection(source=A, destination=B)

you can find all the assemblies where B is destination using:

B.destination_assembly.all().values_list('source', flat=True) # this will include A


来源:https://stackoverflow.com/questions/35645941/django-manytomany-field-through-with-extra-fields-does-not-show-on-both-relation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!