2011-03-21 123 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