Django模型继承和管理系统 [英] Django Model Inheritance and Admin System
问题描述
我正在尝试构建一个管理页面中各种内容的系统。例如,页面可以具有文本内容,超链接内容,视频内容等等。
在我的建模代码中,我有一个基类:
ContentItem(models.Model):
/ pre>
title = models.CharField(max_length = 1000)
page_order = models.IntegerField()
last_update_date = models.DateTimeField(default = datetime.now() )
class Meta:
abstract = True
order = ['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排序,以便在呈现模板时确定页面上的顺序。
类页面(models.Model):
contents = models.ManyToManyField(ContentItem)
title = models.CharField()
<有没有办法使这样的计划工作?或者与其中不同类型的模型有一个关系是有问题的吗?我知道这是一个很好的解决方案和面向对象编程的立场,基本上是使用多态来实现我的优势,但我不确定它在数据库级别是有意义的。
我更需要一些这样的东西:
class Page(models.Model):
pre>
video_contents = models.ManyToManyField VideoContent)
link_contents = models.ManyToManyField(LinkContent)
text_contents = models.ManyToManyField(TextContent)
title = models.CharField()
我知道这可以工作,但是我确定页面上对象放置的方案变得更加困难。我需要遍历所有的内容关系,用page_order排序,然后渲染它们。
我认为在这两种情况下,我想在基类上声明每个特定内容类型可以继承的render()方法。这样,如果我有一个ContentItem列表,我可以使用鸭子打字来渲染它们,而不用担心他们的具体类型。
我的最后一个问题是如何让管理员放置好有了这个?如何让一个简单的方法来查看在一个视图中构成页面的所有ContentItem,这样可以通过更改page_order来轻松地移动它。
感谢阅读这个,让我知道,如果你需要更多的信息。
解决方案这是一个很好的方法。不幸的是,Django的ORM不像你想要的那样顺利地处理模型继承。
page.contents
将包含一个内容
对象的QuerySet。如果要访问子类型,则需要创建一些缩减内容对象的方法。问题是这需要每个对象的查询,这可以快速失控。 此博文描述了一种技术使用select_related()
在一个queryset中获取混合子类型。I'm trying to build a system for managing the various types of content in a page. For example, a page may have text content, hyperlink content, video content, ect.
In my modeling code, I have a base class:
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']
This is the base class for all content items. The page order controls what position it is on the page, for example the item with page_order = 0 should be at the top of the page. Next I define a few specific content models that inherit from this one.
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')
There could be many more such content types. Then I would define a Page model that is composed of all the various content types. Ideally, I could put all the types in on relation based on the base type. So in this one relation you would have a mixture of LinkContents, TextContents, and VideoContents. They would be sorted by page_order to determine their order on the page when rendering the template.
class Page(models.Model): contents = models.ManyToManyField(ContentItem) title = models.CharField()
Is there any way to make such a scheme work? Or is it problematic to have one relation with different types of models in it? I know this is a good solution from and object oriented programming standpoint, basically using polymorphism to my advantage, but I am not sure it makes sense at the database level.
Do I instead need something more like this:
class Page(models.Model): video_contents = models.ManyToManyField(VideoContent) link_contents = models.ManyToManyField(LinkContent) text_contents = models.ManyToManyField(TextContent) title = models.CharField()
I know this would work, but my scheme of determining the placement of the objects on the page becomes more difficult. I would need to traverse all the content relations, sort them by page_order and then render them.
I think in both cases, I want to declare a render() method on the base class that each specific content type can inherit. This way if I have a list of ContentItems I can use duck typing to render them without worrying about their specific type.
My final question is how do I make admin place nice with this? How would I make an easy way to see all of the ContentItems that make up a page in one view, so they can easily be moved around by changing page_order?
Thanks for reading of this, let me know if you need more information.
解决方案This is a fine way to do it. Unfortunately, Django's ORM doesn't handle model inheritance as smoothly as you might want.
page.contents
will contain a QuerySet ofContent
objects. If you want to access the subtypes, you need to create some way of downcasting a content object. The problem is that this requires an query per object, which can rapidly get out of hand. This blog post describes a technique for getting the mixed subtypes in one queryset, usingselect_related()
behind the scenes.这篇关于Django模型继承和管理系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!