我有一个班级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)
在自身实例之间具有ManyToMany Realtionship(connections
)。
我使用中间表Connection
,以便我可以为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)
如果我有两个程序集,让我们说A和B,我通过定义一个新的Connection与A作为源,B作为目的地来连接它们,我得到B作为A的连接(A.connections.all()
),但我不知道不能把A作为B的关系。
如果我不使用中间表,只需models.ManyToManyField("Assembly")
我将A作为B的连接而B作为A的连接。
这里有什么问题?
答案 0 :(得分:2)
我认为您需要为ManyToManyField
指定through_fields
参数。
当Django自动生成你的直通模型时,它知道其中的两个ForeignKey
中的哪一个对应于" local"关系的结束,以及"远程"结束。但是,当您指定自定义中间模型时,这会使其更加困难。 Django可能只是将中间模型中的第一个ForeignKey
指向正确的目标模型,在这两种情况下恰好都是source
(虽然我不确定这是真的如果是这样的话,那可能就是一个错误。)
尝试查看使用through_fields=('source', 'destination')
是否有帮助。
答案 1 :(得分:2)
关注@ koniiiik关于through_fields
的答案:
使用中间模型的递归关系总是被定义为非对称的 - 也就是说,
symmetrical=False
- 因此,有“source”
和“target”
的概念。在这种情况下,'field1'
将被视为关系的“source”
,'field2'
将被视为“target”
。
并且,在您的情况下,它是source
和destination
。
由于您使用的是中间模型Connection
,因此该关系不再对称。因此,A.connections.all()
和B.connections.all()
会返回不同的结果。
A.connections.all() #all assemblies where A is source
B.connections.all() # all assemblies where B is source
如果您添加连接:
Connection(source=A, destination=B)
您可以使用以下方法找到B所在的所有程序集:
B.destination_assembly.all().values_list('source', flat=True) # this will include A