说,有一个页面有许多与之关联的块。每个块都需要自定义渲染,保存和数据。
从代码的角度来看,最简单的是为每个模型定义不同的类(因此,模型)。简化如下:
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中),它定义了一个保存,它通过实例化相同的模型来保存数据及其“类型”。然后创建一个模板标记和一个过滤器,根据模型的类型调用渲染,保存和其他方法。
答案 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命令来转储/重新加载测试数据集来解决它。