2011-03-21 210 views
6

我試圖建立一個系統來管理頁面中的各種類型的內容。例如,一個頁面可能包含文本內容,超鏈接內容,視頻內容等。Django模型繼承和管理系統

在我的建模代碼,我有一個基類:

class ContentItem(models.Model): 
    title = models.CharField(max_length=1000) 
    page_order = models.IntegerField() 
    last_update_date = models.DateTimeField(default=datetime.now()) 

    class Meta: 
     abstract = True 
     ordering = ['page_order', 'last_update_date', 'title'] 

這是所有的內容項目的基類。頁面順序控制它在頁面上的位置,例如page_order = 0的項目應位於頁面的頂部。接下來我定義了一些從這個繼承的特定內容模型。

class LinkContent(ContentItem): 
    url = models.URLField() 
    link_text = models.CharField(max_lenth=1000) 

class TextContent(ContentItem): 
text = models.CharField() 


class VideoContent(ContentItem): 
     title = models.CharField() 
     video_file = models.FieldField(upload_to = 'videos') 

可能有更多這樣的內容類型。然後,我將定義一個由所有各種內容類型組成的Page模型。理想情況下,我可以根據基類型將所有類型放入關係中。因此,在這種關係中,您可能會混合使用LinkContents,TextContents和VideoContents。它們將按照page_order排序,以在呈現模板時確定它們在頁面上的順序。

class Page(models.Model): 
    contents = models.ManyToManyField(ContentItem) 
    title = models.CharField() 

有什麼方法可以使這樣的計劃工作?或者它與其中不同類型的模型有一個關係有問題嗎?我知道這是從面向對象編程的角度來看的一個很好的解決方案,基本上使用多態對我有利,但我不確定它在數據庫級別上有意義。

難道我反而需要更多的東西是這樣的:

class Page(models.Model): 
    video_contents = models.ManyToManyField(VideoContent) 
    link_contents = models.ManyToManyField(LinkContent) 
    text_contents = models.ManyToManyField(TextContent) 
    title = models.CharField() 

我知道這會工作,但我的判斷網頁上的對象的安置方案變得更加困難。我需要遍歷所有的內容關係,按page_order對它們進行排序,然後渲染它們。

我認爲在這兩種情況下,我想聲明一個基類的render()方法,每個特定的內容類型都可以繼承。這樣,如果我有一個ContentItems列表,我可以使用鴨子打字來呈現它們,而不用擔心它們的具體類型。

我的最後一個問題是如何讓管理員把它放在這個地方?我怎樣才能讓一個簡單的方法在一個視圖中看到組成頁面的所有ContentItem,這樣他們就可以輕鬆地通過改變page_order來移動?

感謝您閱讀本文,如果您需要更多信息,請告知我們。

回答

3

這是一個很好的方法。不幸的是,Django的ORM不能像你想要的那樣順利地處理模型繼承。 page.contents將包含Content對象的QuerySet。如果你想訪問子類型,你需要創建一些向下轉換內容對象的方式。問題是這需要每個對象的查詢,這可能會很快失去控制。 This blog post描述了一種在後臺使用select_related()來獲得一個查詢集合中的混合子類型的技術。

+1

謝謝@jcdyer。這是非常有用的信息。但我仍然不清楚的一件事是如何在Admin界面中完成這項工作。理想情況下,我想要一種方式來列出網頁的內容,並根據具體的類別顯示相應的管理員表單。例如,如果頁面的內容屬性中包含2個LinkContents和1個TextContent,我希望前兩個可以使用鏈接表單編輯,而另一個使用文本表單編輯。有沒有簡單的方法來做這樣的事情?我做了很多管理定製,但從未見過類似的東西。 – Jon 2011-03-21 20:09:46