Django模型通用建模

时间:2009-12-21 12:07:28

标签: database django data-modeling modeling django-orm

说,有一个页面有许多与之关联的块。每个块都需要自定义渲染,保存和数据。

从代码的角度来看,最简单的是为每个模型定义不同的类(因此,模型)。简化如下:

class Page(models.Model):
    name = models.CharField(max_length=64)

class Block(models.Model):
    page = models.ForeignKey(Page)

    class Meta():
        abstract = True

class BlockType1(Block):

    other_data = models.CharField(max_length=32)

    def render(self):
        """Some "stuff" here """
        pass

class BlockType2(Block):

    other_data2 = models.CharField(max_length=32)

    def render(self):
        """Some "other stuff" here """
        pass

但是,

  • 即使使用此代码,我也无法执行page.block_set.all()之类的查询来获取所有不同的块,无论块类型如何。
  • 上述原因是,每个模型定义了一个不同的表;使用链接模型和通用外键来解决问题可以解决问题,但每页仍会留下多个数据库表查询。

对它进行建模的正确方法是什么?是否可以以某种方式使用通用外键(或其他内容),以便将数据存储在同一数据库表中,从而实现继承范例。

更新

我的观点是,我如何仍然可以使用OOP范例。使用与这么多 ifs相同的方法不是我想要做的。

在我看来,最好的解决方案是创建单独的标准python类(最好在不同的blocks.py中),它定义了一个保存,它通过实例化相同的模型来保存数据及其“类型”。然后创建一个模板标记和一个过滤器,根据模型的类型调用渲染,保存和其他方法。

2 个答案:

答案 0 :(得分:4)

不要在数据库中为页面建模。页面是演示文稿。

首先 - 最重要的是 - 正确获取数据。

“每个街区都需要自定义渲染,保存和数据。”打破这一点:你有独特的数据。从模型角度忽略“块”和“渲染”。只需定义数据而不考虑演示文稿

严重。只需在模型中定义数据,无需考虑演示或渲染或其他任何内容。正确获取数据模型。

如果您混淆模型和演示文稿,您将永远无法正常工作。如果你确实让它发挥作用,你就永远无法扩展或重复使用它。

第二次 - 只有在数据模型正确之后 - 您才能转向演示文稿。

只需使用HTML <div>标记和样式表即可完成“块”。先尝试一下。 毕竟,该模型的工作原理非常简单。这只是HTML和CSS,与模型分开。

您的“块”可能需要自定义模板标记来创建更复杂的条件HTML。试试那一秒。

在极端情况下,您的“块”可能非常复杂,您必须编写专门的视图函数来将多个对象转换为HTML。这是非常非常罕见的。在确定无法使用模板标记执行此操作之前,不应执行此操作。


编辑。

“查询不同的外部数据源”

“将具有save方法的简单类(不是Models)分开,写入同一个数据库表。”

你有三个完全不同的,不相关的,分开的东西。

  • 模型。持久模型。使用save()方法。这些非常非常少。 他们有属性和一些方法。没有“查询不同的外部数据源”。没有“以HTML呈现”。

  • 外部数据源。这些是获取数据的普通Python类。 这些对象(1)获取外部数据,(2)创建Model对象。没有别的。没有“坚持”。没有“以HTML呈现”。

  • 演示。这些是呈现Model对象的普通Django模板。没有外部查询。没有持久性。

答案 1 :(得分:1)

我刚刚完成了一个在黑桃中遇到这个问题的系统原型:一个基础产品类和大约200个细节类别,它们各不相同。在很多情况下,我们正在对Product进行常规查询,但是后来想要在渲染期间处理子类特定的细节。例如。从供应商X获取所有产品,但显示的特定子类的每个组的模板略有不同。

我为基类添加了GenericForeignKey的隐藏字段,并自动填充content_type&amp; save()时子类的object_id。当我们有一个通用的Product对象时,我们可以说obj = prod.detail然后直接使用子类对象。花了大约20行代码,效果很好。

我们在测试过程中遇到的问题是manage.py dumpdata后跟manage.py loaddata不断投掷Integrity Errors。事实证明这是一个众所周知的问题,预计在1.2版本中会有一个修复。我们通过使用mysql命令来转储/重新加载测试数据集来解决它。