构建一个在应用程序之间具有许多共同功能的django应用程序

时间:2012-09-14 04:34:14

标签: django

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

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

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

编辑:这些模型有一些共同的字段,但这就是相似性结束的地方。您可以拥有学校,活动或新闻文章的模型(您可以看到它们与人类的观点完全不同)。我将根据需要添加或删除这些模型,因此,我必须拥有单独的应用程序。看起来您需要创建一些您在所有这些应用程序中调用的常见内容,但这个常见的集合存在于模型和视图中(几乎需要一个能够完成所有这些工作的框架)。

1 个答案:

答案 0 :(得分: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,因此您可以创建另一个继承自这两个类的视图,从而执行这两个任务。此外,一旦从某个基本视图继承,就可以覆盖定义的任何函数基类,从而提供更大的灵活性。

这对于为许多类似视图执行常见任务非常有用,但最大限度地减少了要编写的代码量。


希望这能为您提供有关如何构建项目/应用程序的一些想法。