1

我有一个关于如何在 django 中构建这个应用程序的高级问题。

我有一些模型将经历类似的操作,这些操作将由视图对它们执行(如创建、编辑、保存等)。您还将有一些独特的操作。其中许多操作是相同的,我不想重复代码。这些模型将具有一些共同的字段,它们也将具有独特的字段。设计这个的最佳方法是什么?

不同的模型将是不同的应用程序。例如,模型可以是学校、教堂或餐厅。因此,您将拥有三个应用程序。我想这些模型是抽象类的子类。这些视图还将具有对所有这三个应用程序相同的一些操作。不知道如何编写一组通用代码,并让这三个应用程序继承一些东西,然后在需要时进行自定义。我只需要一些指针/方向。

编辑:这些模型有一些共同的领域,但这是相似性结束的地方。您可以拥有学校、活动或新闻文章的模型(正如您所看到的,从人类的角度来看,它们可能完全不同)。我将根据需要添加或删除这些模型,因此,我必须有单独的应用程序。似乎您需要创建在所有这些应用程序中都可以调用的通用内容,但是模型和视图存在这个通用集合(我认为几乎需要一个框架来完成所有这些工作)。

4

1 回答 1

4

这更像是一个概念性的答案。

如果模型非常相似,我认为它们应该属于同一个应用程序。我的推理如下。在我看来,应用程序是一组相关数据以及与该数据相关联的业务逻辑,甚至可能是关于如何呈现该数据的一些逻辑。因此,如果模型非常常见,那么数据似乎有些相关,因此应该在同一个应用程序中。

然而,根据我的经验,一些应用程序可以增长,我在一个应用程序中拥有超过 20 个模型。这可能很难在一个models.py文件中管理,因此我喜欢将模型分解为一个包。那么应用程序的结构可能如下所示:

project/
  manage.py
  project/
    __init__.py
    settings.py
    ...
  app/
    __init__.py
    ...
    models/
      __init__.py
      ...

唯一的事情是,如果你这样做,那么你必须导入模型__init__.py文件中的所有模型并将它们包含在__all__变量中。这样,即使模型被构造为一个包,在其余代码中,您也可以将它们用作模块。

这种方法的优点是您的模型是模块化的,这使得维护变得更加容易,并将相关数据保存在一个地方。


至于业务逻辑,我认为继承应该解决很多问题。您始终可以从多个类继承。这允许您创建一组具有特定功能的基类/模型,然后只从模型的适当基类继承。这将允许您尽可能多地重用代码。

另一种方法是使用元类。这个想法是您定义一个构建不同类的实例的类。例子:

class FooMetaClass(type):
    def __new__(cls, name, bases, dict):
        # do some logic
        return super(FooMetaClass, cls).__new__(cls, name, bases, dict)

class FooClass(object):
    __metaclass__ = FooMetaClass
    ...

所以想法是您可以在 中包含一些设置属性FooClass,并根据这些属性甚至它们的值,元类可以构建该类的自定义实例。此时你甚至可以生成动态的东西!

我发现这种方法有用几次,但在大多数情况下,我认为子分类应该足够了。


对于演示,基于类的视图是完美的。在这几年的 DjangoCon 中,Kenneth Love 就基于类的视图做了一个非常好的演讲。在这里你可以看到幻灯片:https ://speakerdeck.com/u/kennethlove/p/views-can-be-classy ,希望视频能很快发布。大的想法是基于类的视图与基于函数的视图相同,除了它的结构方式。

我知道在我的许多项目中,我的许多观点几乎是相同的。在视图的开头发生了一些事情,这在许多视图中非常相似。然后是视图的一些中间/肉类部分,这通常是每个视图所独有的。然后是视图的最后部分,我在其中构造上下文字典并返回响应。所以我和许多其他开发人员最终做的是拥有十亿个辅助函数,我们在其他视图中调用它们来完成某些重复性任务。然而,这种方法使代码更难阅读,有时会引入不必要的抽象,因为您必须将许多参数传递给辅助函数,最终感觉不对。

这就是基于类的视图的用武之地。它们与基于函数的视图完全相同,只是它们将视图分解为多个函数调用。因此,一个函数可以负责获取对象,另一个函数负责构建上下文,等等。然后,当所有这些函数组合在一起时,几乎可以执行与函数视图中相同的代码。然而,这带来了一个主要优势。您可以继承视图。因此,您可以拥有一个用于执行任务 a 的基类视图,以及另一个用于执行任务 b 的视图,因此您可以创建另一个从两个类继承的视图,从而执行这两个任务。此外,一旦您从某个基本视图继承,您就可以覆盖定义的任何函数基类,从而提供更大的灵活性。

这是一种非常有用的设计模式,可以为许多类似的视图执行常见任务,同时最大限度地减少要编写的代码量。


希望这能给您一些关于如何构建项目/应用程序的想法。

于 2012-09-14T05:52:35.260 回答