2017-05-25 65 views
0

我有以下型號:Django的模型關係最好的解決辦法

BasketFruit

一個Basket可以在他們多次Fruit對象和Fruit屬於一個Basket。每個Fruit都可以手動訂購,這樣當它們列出時,它們將顯示它們的保存順序。到現在爲止還挺好。

class Basket (models.Model): 
    # A fruit basket 
    name = models.CharField(max_length=100) 
    is_virtual = models.BooleanField(default=False) 
    # This is just a badly constructed example of how a list 
    # of basket primary keys are saved when creating the virtual basket 
    # This is only for demonstration purposes to solve the overall modelling issue 
    virtual_baskets = models.TextField(null=True) 

class Fruit (models.Model): 
    # The basket this fruit belongs to 
    basket = models.ForeignKey("Basket", related_name="fruits", on_delete=models.CASCADE) 

    # Manually sorted order 
    order = models.PositiveIntegerField(default=0) 

然而,有一個名爲is_virtualBasket一個標誌,它允許用戶創建虛擬聯合體筐從現有的,真正的籃子,在你最終打破規則稍微的:一個虛擬的籃子實際上可合併兩個現有的Baskets,因此來自兩個籃子的Fruit。我需要能夠讓用戶手動對這些籃子中的Fruit進行排序和重新排序,而不會覆蓋原始籃子中的排序。

舉個例子:

Basket A按順序包含:蘋果,香蕉

Basket B按順序包含:橙,葡萄

我現在想創建一個虛擬Basket C會顯示來自A和B的水果如此:

蘋果,葡萄,香蕉,橙色

需要注意的是:虛擬籃子簡單地結合了其他各種籃子的結果。對於用戶來說,它仍然是一個有效的籃子,他們應該可以重新訂購水果。

如何爲這種訂購關係建模?我正在考慮增加一個新的模型:

class FruitAppearance (models.Model): 
    # The basket this appearance is tied to 
    basket = models.ForeignKey("Basket", related_name="manually_sorted_fruits", on_delete=models.CASCADE) 

    # The fruit it represents 
    fruit = models.ForeignKey("Fruit", on_delete=models.CASCADE) 

    # Order 
    order = models.PositiveIntegerField(default=0) 

我是否認爲它是正確的?有沒有更好的辦法?我應該在現有的FruitBasket模型之一中使用ManyToManyField嗎?

+0

水果屬於一個籃子,不管它是否虛擬? –

+0

正確,它只屬於一個真正的籃子,但可以用不同的方式在虛擬籃子中呈現 – strangetimes

+0

虛擬籃子當然可以保存,手動水果排序也應該持續 – strangetimes

回答

0
class Basket(models.Model): 
    name = models.CharField(max_length=100) 
    fruits = models.ManyToMany("Fruit", through="FruitBasket") 
    ... 

class Fruit(models.Model): 
    ... 

class FruitBasket(models.Model: 
    basket = models.ForeignKey("Basket", on_delete=models.CASCADE) 
    fruit = models.ForeignKey("Fruit", on_delete=models.CASCADE) 
    order = models.PositiveIntegerField(default=0) 
    ... 

這樣,您將有一些數據冗餘,但也許能在每一個籃子水果設置不同級數。

+0

謝謝,雖然我很想知道,這裏的FruitBasket和我創建的FruitAppearance模型類完全一樣。我看到的唯一區別是籃子中增加的冗餘(如你所說)。不會讓那裏有所作爲嗎? – strangetimes

+0

是的,果實冗餘正是允許您爲不同籃子中的單一水果設置不同的順序值(例如,檸檬在籃子A中具有訂單等級1但在籃子B中具有訂單等級4)。沒有這種冗餘,您只能爲水果設置固定的訂單水平。 –

+0

我明白了..我想在db模型層次上,類會創建所需的中間表,但是從Bucket訪問的'fruits'屬性將以編程方式允許我們訪問/設置這些屬性。當然。謝謝,我認爲這是不幸的,但它是模型的唯一合理的補充,以使其發揮作用! – strangetimes

0

我會建議如下。 將您的模型Basket和Virtual Basket分開,結果刪除虛擬域。

因此,每個水果可以屬於一個籃子(ForeignKey),但同時到多個虛擬籃子(ManyToManyField)。在manytomany字段中使用參數throught幷包含另一個模型,該模型將僅存儲該特定虛擬籃子的水果順序。

class Fruit (models.Model): 
    # The basket this fruit belongs to 
    basket = models.ForeignKey("Basket", related_name="fruits", on_delete=models.CASCADE) 
    virtual_basket = models.ManyToManyField(Fruit, through='FruitOrdering') 

    # Manually sorted order 
    order = models.PositiveIntegerField(default=0) 
+0

這不是一個可行的解決方案。水果將永遠存在,並由實際創建的籃子所擁有。由於以上是真實應用程序嘗試執行的簡單示例,因此真正的應用程序會創建複雜的搜索過濾器,並從現有的東西列表中創建智能列表。想一下聯繫人應用程序,其中聯繫人來自各種賬戶/提供商,我們創建虛擬列表。每個供應商都會訂購聯繫人,然後我們需要在我們的智能列表表示中重新排序。 – strangetimes