模型/视图之间的分隔旨在将显示与数据分离。您对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