2016-02-26 80 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

相關問題