2016-02-26 69 views
3

我有一个类AssemblyDjango的多对多场通过使用额外字段不会对双方关系显示

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) 

具有的本身(connections)实例之间的多对多Realtionship。 我使用中间表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,和我通过定义一个与源和B作为目的地的新连接将它们连接起来,我得到B,为的连接(A.connections.all()),但我不A不会成为B的联系人。

如果我不使用中间表,只需要一个models.ManyToManyField("Assembly")我得到A作为B的连接,B作为A的连接。

这是什么问题?

+0

嗯..没有指定related_name,你有没有试过'assembly_set从B的一面来看? – schwobaseggl

+0

如果我没有指定一个related_name,我得到一个错误(不记得它是什么),因为我使用了两次相同的ForeignKey。 – Bouni

回答

2

我想你需要指定through_fields参数到ManyToManyField

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

试着看看是否使用through_fields=('source', 'destination')有帮助。

+0

我只是尝试了'through_fields',但它没有帮助。 – Bouni

+0

@Bouni我在答案中解释了为什么你不能在A和B之间获得对称连接。但是,你必须使用'through_fields'来正确定义源和目的地是什么。 – AKS

+0

@AKS在[其他答案](http://stackoverflow.com/a/35647525/687488)中有一个好处 - 当您使用自定义的'through'模型时,关系自动不再是对称的,这意味着每个关系的一面会看到一组不同的对象。对称性是通过在中间表中为每对相关对象使用两行来实现的,因此如果要使用自定义模型,则必须自己执行此操作。这也意味着任何额外的数据将被存储在数据库中两次。 – koniiiik

2

在@ koniiiik的回答跟进有关through_fields

使用中间模型递归关系总是被定义为非对称的 - 也就是说,用symmetrical=False - 因此,有“source”的概念,一个“target”。在这种情况下,'field1'将被视为关系的“source”,并将'field2'视为“target”

并且在你的情况下它是sourcedestination

由于您使用的是中介模型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 
+0

建议'... values_list('source_assembly',flat = True)'根本没有结果。 – Bouni

+0

您是否使用'through_fields'更新了声明'models.ManyToManyField(“Assembly”,through =“Connection”,through_fields =('source','destination'))' – AKS

+0

是的,我已经添加了through_fields几个分钟,然后我尝试了您的建议,因为@koniiik的建议 – Bouni

相关问题