2009-12-21 73 views
2

说,有一个网页有很多块与它关联。每个块都需要自定义渲染,保存和数据。Django模型通用建模

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

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中),该类定义了一个保存,通过实例化相同的模型来保存数据及其“类型”。然后创建一个模板标签和一个过滤器,根据模型的类型调用渲染,保存和其他方法。

回答

4

不要在数据库中建模页面。页面是一个介绍的东西。

第一个 - 最重要的是 - 获取正确的数据。

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

说真的。只需在模型中定义数据,而无需考虑演示文稿或任何其他内容。正确获取数据模型。

如果您混淆模型和演示文稿,您将永远得不到任何工作。如果你确实得到它的工作,你将永远无法扩展或重用它。

- 只有在数据模型是正确的 - 你可以打开,以演示。

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

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

您的“块”可能 - 在极端情况下 - 非常复杂,您必须编写专门的视图函数将几个对象转换为HTML。这是非常非常罕见的。你不应该这样做,直到你确信你不能用模板标签来做到这一点。


编辑。

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

“单独的简单类(不模型),其具有保存方法,即写入相同的数据库表”。

你有三个完全不同的,无关的,独立的东西。

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

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

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

+0

指向正确的数据模型,谢谢。 在我的情况下,对于不同的块类型,我需要查询不同的外部数据源并呈现完全不同的html。此外,缓存数据(在块级)因此,块标签并没有真正的帮助。我想的只是单独的简单类(不是模型),它们有一个保存方法,写入同一个数据库表。 – 2009-12-21 15:48:22

1

我完成了一个原型系统已经在黑桃这个问题:基础产品类和200类的细节是大相径庭。在许多情况下,我们正在对产品进行常规查询,但接下来想要在渲染过程中处理子类特定的细节。例如。从供应商X获得所有产品,但显示的是与特定子类中的每个组略有不同的模板。

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

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