Python Django ManyToMany字段和额外字段在这两种关系上都不显示

Python Django ManyToMany字段和额外字段在这两种关系上都不显示,python,django,many-to-many,django-orm,Python,Django,Many To Many,Django Orm,我有一个类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)

我有一个类
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)
它自身的实例之间有很多关系(
连接
)。 我使用一个中间表
Connection
,这样我就可以为
程序集的两个实例之间的连接提供额外的字段

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,我通过定义一个新的连接将它们连接起来,其中A作为源,B作为目标,我得到B作为A的连接(
A.connections.all()
),但我没有得到A作为B的连接

如果我不使用中间表,只使用a
models.ManyToManyField(“Assembly”)
我得到a作为B的连接,B作为a的连接


我的问题是什么?

我认为您需要为
ManyToManyField
指定参数

当Django自动生成直通模型时,它知道其中两个
ForeignKey
s中的哪个对应于关系的“本地”端,哪个是“远程”端。但是,当您指定自定义中介模型时,这会使其更加困难。Django可能只是将中间模型中的第一个
ForeignKey
指向正确的目标模型,在这两种情况下都恰好是
source
(虽然我不确定这是否真的是这样,如果是,可能是一个bug)


尝试查看使用
通过_fields=('source','destination')
是否有帮助。

跟进@koniik关于以下方面的回答:

使用中间模型的递归关系总是被定义为非对称的,即
symmetric=False
,因此有
“源”
“目标”
的概念。在这种情况下,
'field1'
将被视为关系的
“源”
,而
'field2'
将被视为
“目标”

在您的例子中,它是
目标

由于您使用的是中间模型
连接
,因此关系不再是对称的。因此,
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

隐马尔可夫模型。。在没有指定相关名称的情况下,您是否从B的角度尝试了
assembly\u set
因为我使用了两次相同的外键。我只是通过_字段尝试了
,但没有帮助。@Bouni我在回答中解释了为什么A和B之间无法获得对称连接。但是,您必须使用
通过
字段来正确定义什么是源,什么是目标。@AKS有一个很好的切入点–当您使用自定义
通过
模型时,关系自动不再对称,这意味着关系的每一边都将看到不同的对象集。对称性是通过为每对相关对象使用中间表中的两行来实现的,因此,如果要使用自定义直通模型,则必须自己执行此操作。这也意味着任何额外的数据都将在数据库中存储两次。@Koniik在数据库中添加两行的观点非常好,但它确实需要额外的管理和维护。:)我想我会用简单的方法,使用默认的Django manytomy字段,而不使用额外的字段。无论如何,谢谢你的建议!建议
…values\u list('source\u assembly',flat=True)
根本没有给我任何结果。您是否使用
through\u字段更新声明,例如
模型。ManyToManyField(“assembly”,through=“Connection”,through\u fields=('source',destination'))
是,在我尝试你的建议前几分钟,我已经添加了through_字段,因为@koniik的建议如果可能的话;请删除现有条目、迁移、添加新连接,并查看是否使用
B.destination\u assembly.all()
?好的,我将尝试作为最后一个测试:-)