Django模型继承和管理系统 [英] Django Model Inheritance and Admin System

查看:65
本文介绍了Django模型继承和管理系统的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个管理页面中各种内容的系统。例如,页面可以具有文本内容,超链接内容,视频内容等等。



在我的建模代码中,我有一个基类:

  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
order = ['page_order','last_update_date','title']
/ pre>

这是所有内容项的基类。页面顺序控制页面上的位置,例如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):
video_contents = models.ManyToManyField VideoContent)
link_contents = models.ManyToManyField(LinkContent)
text_contents = models.ManyToManyField(TextContent)
title = models.CharField()
pre>

我知道这可以工作,但是我确定页面上对象放置的方案变得更加困难。我需要遍历所有的内容关系,用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 of Content 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, using select_related() behind the scenes.

这篇关于Django模型继承和管理系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆