模型/視圖之間的分隔旨在將顯示與數據分離。您對Question
的多態模型層次結構的初始描述確實是一種有效的方法。
你真的想在這裏做的是考慮使用Django的模型繼承來處理數據的層次結構,即有:
BaseQuestion <- FreeQuestion,
MultipleChoiceQuestion,
SlidingScaleQuestion etc.
然後你就可以建立一個BaseQuestionView
知道如何顯示BaseQuestion
(例如渲染問題字符串,它的風格,什麼不可以),並使用相同的原理結構:
BaseQuestionView <- FreeQuestionView,
MultipleChoiceQuestionView,
SlidingScaleQuestionView
可以使BaseQuestionView抽象,以拉都BaseQuestion
模型實例從一個數據庫並且調用分別在FreeQuestionView
,MultipleChoiceQuestionView
,SlidingScaleQuestionView
子類中實施的摘要render_question
方法。因此FreeQuestionView
知道它與FreeQuestion
模型一起工作,並且只實現瞭如何爲答案呈現小部件(textfield)。 MultipleChoiceQuestionView
只會實現如何渲染收音機等。
換句話說,它幾乎就是你在第一種情況下呈現的內容,除了渲染實現在View classes not Model類中。
當你想以不同的方式渲染同一類對象時,可以應用相同的原理。
通過模型繼承,您可以使用點符號訪問基本實例的任何子類,即:question.freequestion
。這將返回給您與基礎實例關聯的FreeQuestion實例,或者如果這不是它的類,則會引發Question.DoesNotExist
。
使用基於類的視圖,你可以添加Mixins,它可以根據天氣來呈現不同的問題,這是一個FreeQuestion,MultipleChoiceQuestion,使用python的MRO模式,或者你可以對它們進行子類化。
據我所知,Django沒有自動的方式來使繼承模型和繼承視圖之間的關聯,你必須自己做映射。
也許最簡單的方法是明確請求所有與FreeQuestions,MultipleChoiceQuestions等相關的初始Question QuerySet相匹配的實例,然後將它們投入列表中,然後將它們提交給主渲染器,然後再通過map[question.__class__]
查找mixin的渲染器方法。或者,您可以將問題類型保留在基類中,以避免必須處理類映射,並讓數據庫在這方面爲您提供幫助。
但是,通常情況下,您不希望模型行爲對同一類進行動態更改(這正是您使用BaseQuestion進行的有效操作)。在設計REST時,尤其如此,因爲您希望顯式URL映射到顯式具體而非抽象類型。
感謝您的迴應,它似乎是一個很好的解決方案。我確實有一個後續:我如何確保'BaseQuestionView'的正確子類與'BaseQuestion'的特定實例相關聯?如果每個'BaseQuestion'實例在運行時被實例化,那麼當每個問題被實例化時,我會將每個問題與'BaseQuestionView'的正確子類的代理關聯起來。但我不確定使用數據庫查詢填充問題列表的最佳方式是什麼。你將如何實施這個協會? – solarein 2012-07-12 02:29:47
查看更新答案。 – astevanovic 2012-07-12 13:06:06