问题
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 ForeignKey
s 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