2009-12-21 77 views
2

說,有一個網頁有很多塊與它關聯。每個塊都需要自定義渲染,保存和數據。Django模型通用建模

最簡單的是,從代碼的角度來說,爲每個模型定義不同的類(因此,模型)。簡化如下:

class Page(models.Model): 
    name = models.CharField(max_length=64) 

class Block(models.Model): 
    page = models.ForeignKey(Page) 

    class Meta(): 
     abstract = True 

class BlockType1(Block): 

    other_data = models.CharField(max_length=32) 

    def render(self): 
     """Some "stuff" here """ 
     pass 

class BlockType2(Block): 

    other_data2 = models.CharField(max_length=32) 

    def render(self): 
     """Some "other stuff" here """ 
     pass 

但隨後,

  • 即使有這樣的代碼,我不能做這樣page.block_set.all()查詢來獲取所有不同的塊,不論塊類型的。
  • 以上的原因是,每個模型定義了不同的表格;儘量使用鏈接模型和通用外鍵來實現它,可以解決問題,但它仍然會在每個頁面上留下多個數據庫表查詢。

什麼是建模它的正確方法?是否可以以某種方式使用泛型外鍵(或其他),將數據存儲在同一個數據庫表中,但實現了繼承範例。

更新:

我的觀點是,我如何仍然得到OOP範式工作。使用與相同的方法很多 ifs不是我想要做的。

在我看來,最好的解決方案是創建單獨的標準python類(最好在不同的blocks.py中),該類定義了一個保存,通過實例化相同的模型來保存數據及其「類型」。然後創建一個模板標籤和一個過濾器,根據模型的類型調用渲染,保存和其他方法。

回答

4

不要在數據庫中建模頁面。頁面是一個介紹的東西。

第一個 - 最重要的是 - 獲取正確的數據。

「每個塊都需要自定義渲染,保存和數據。」打破這一點:你有獨特的數據。從模型的角度忽略「塊」和「渲染」。只需定義數據而不考慮演示

說真的。只需在模型中定義數據,而無需考慮演示文稿或任何其他內容。正確獲取數據模型。

如果您混淆模型和演示文稿,您將永遠得不到任何工作。如果你確實得到它的工作,你將永遠無法擴展或重用它。

- 只有在數據模型是正確的 - 你可以打開,以演示。

您的「塊」可以簡單地用HTML <div>標籤和樣式表完成。先嚐試一下。畢竟,模型的工作原理非常簡單。這只是HTML和CSS,與模型分開。

您的「塊」可能需要自定義模板標籤才能創建更復雜的條件HTML。試試看。

您的「塊」可能 - 在極端情況下 - 非常複雜,您必須編寫專門的視圖函數將幾個對象轉換爲HTML。這是非常非常罕見的。你不應該這樣做,直到你確信你不能用模板標籤來做到這一點。


編輯。

「查詢不同的外部數據源的」

「單獨的簡單類(不模型),其具有保存方法,即寫入相同的數據庫表」。

你有三個完全不同的,無關的,獨立的東西。

  • 型號。持久性模型。用save()方法。這些做得非常非常少。 他們有屬性和一些方法。否「查詢不同的外部數據源」。沒有「在HTML中渲染」。

  • 外部數據源。這些是獲取數據的普通Python類。這些對象(1)獲取外部數據和(2)創建模型對象。沒有別的。沒有「持久性」。沒有「在HTML中渲染」。

  • 演示文稿。這些是呈現模型對象的普通Django模板。沒有外部查詢。沒有持久性。

+0

指向正確的數據模型,謝謝。 在我的情況下,對於不同的塊類型,我需要查詢不同的外部數據源並呈現完全不同的html。此外,緩存數據(在塊級)因此,塊標籤並沒有真正的幫助。我想的只是單獨的簡單類(不是模型),它們有一個保存方法,寫入同一個數據庫表。 – 2009-12-21 15:48:22

1

我完成了一個原型系統已經在黑桃這個問題:基礎產品類和200類的細節是大相徑庭。在許多情況下,我們正在對產品進行常規查詢,但接下來想要在渲染過程中處理子類特定的細節。例如。從供應商X獲得所有產品,但顯示的是與特定子類中的每個組略有不同的模板。

我添加隱藏字段的GenericForeignKey基類,並在保存()時它自動填充子類的content_type & object_id。當我們有一個通用的Product對象時,我們可以說obj = prod.detail然後直接與子類對象一起工作。花了大約20行代碼,它工作得很好。

我們在測試過程中遇到的一個問題是:manage.py dumpdata其次是manage.py loaddata不斷拋出Integrity Errors。原來這是一個衆所周知的問題,預計在1.2版本中會有一個修復。我們通過使用mysql命令來轉儲/重新加載測試數據集。