2

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

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

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 范式继续工作对这么多if使用相同的方法不是我想要做的。

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

4

2 回答 2

4

不要在数据库中为页面建模。页面是一种展示的东西。

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

“而且每个块都需要自定义渲染、保存和数据。” 打破这个:你有独特的数据。从模型的角度忽略“块”和“渲染”。只定义数据而不考虑表示

严重地。只需在模型中定义数据,无需考虑呈现或渲染或其他任何事情。获取正确的数据模型。

如果您混淆了模型和演示文稿,您将永远无法正常工作。如果你真的让它工作,你将永远无法扩展或重用它。

其次——只有在数据模型正确之后——你才能转向展示。

您的“块”可以简单地使用 HTML<div>标记和样式表来完成。先试试那个。毕竟,该模型有效并且非常简单。这只是 HTML 和 CSS,与模型分开。

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

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


编辑。

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

“分离具有保存方法的简单类(不是模型),它们写入同一个数据库表。”

你有三个完全不同的、不相关的、独立的东西。

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

  • 外部数据源。这些是获取数据的普通 Python 类。这些对象 (1) 获取外部数据和 (2) 创建模型对象。没有别的了。没有“坚持”。没有“在 HTML 中呈现”。

  • 介绍。这些是呈现模型对象的普通 Django 模板。没有外部查询。没有坚持。

于 2009-12-21T12:33:15.597 回答
1

我刚刚完成了一个存在这个问题的系统原型:一个基础产品类和大约 200 个变化很大的细节类。在很多情况下,我们正在对 Product 进行一般查询,但随后又想在渲染期间处理特定于子类的细节。例如,从 Vendor X 获取所有产品,但针对来自特定子类的每个组显示略有不同的模板。

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

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

于 2009-12-21T16:33:00.880 回答