【问题标题】:Django Model Inheritance and Admin SystemDjango 模型继承和管理系统
【发布时间】:2011-03-21 14:08:57
【问题描述】:

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

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

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() 方法。这样,如果我有一个 ContentItem 列表,我可以使用鸭子类型来呈现它们,而不必担心它们的具体类型。

我的最后一个问题是如何使管理场所变得更好?我如何以一种简单的方式在一个视图中查看构成页面的所有 ContentItem,以便可以通过更改 page_order 轻松移动它们?

感谢您阅读本文,如果您需要更多信息,请告诉我。

【问题讨论】:

    标签: python django django-models django-admin


    【解决方案1】:

    这是一个很好的方法。不幸的是,Django 的 ORM 并没有像您希望的那样顺利地处理模型继承。 page.contents 将包含 Content 对象的 QuerySet。如果要访问子类型,则需要创建某种方式来向下转换内容对象。问题是这需要对每个对象进行一次查询,这可能会很快失控。 This blog post 描述了一种在一个查询集中获取混合子类型的技术,在后台使用 select_related()

    【讨论】:

    • 谢谢@jcdyer。这是非常有用的信息。我仍然不清楚的一件事是如何在管理界面中完成这项工作。理想情况下,我想要一种列出页面内容并根据特定类为项目显示适当管理表单的方法。例如,如果一个页面的内容属性中有 2 个链接内容和 1 个文本内容,我希望前两个可以使用链接表单进行编辑,而另一个可以使用文本表单进行编辑。有没有一种简单的方法来做这样的事情?我做了很多管理员自定义,但从未见过这样的事情。
    猜你喜欢
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多