Django:当应用程序似乎已经耦合时,如何完全解耦应用程序?

时间:2018-02-16 17:17:27

标签: python django

注意:我不是正确的 python程序员...但我广泛使用python。我做的事情就像写类继承,使用迭代器和理解等等。我的观点是我没有完全掌握语言,例如什么完全构成一个python对象,除了指定一个模块之外,还需要__init__.py等等。关于Django,我编写了多应用程序站点(在SO的帮助下)并且非常喜欢Django的模板系统,块以及它们如何嵌套。现在我的应用程序是完全解耦和可重用的吗?这是这篇文章的主题。

我声明了这个免责声明,因为许多Django资源似乎都认为人们知道这些事情。这使得理解一些文档和S.O.对于只是(子力量) - 用户的人来说难以解决的问题。所以请记住这个问题。

问题

这些问题的灵感来自When to create a new app with startapp in django?问题@håkananswer @antti rasinen问题,PyCon presentation链接到James Bennett的2008 Firefox: <input type="number"> }

贝内特演讲的几个要点是:

  1. 网站是应用程序的集合
  2. 一个应用程序做一件事,一件好事
  3. 这引导我进入他的部分&#34;项目耦合杀死了重复使用&#34;提到:

    • 直接在Python路径上的单个模块(注册,标记等)
    • 包下的相关模块(ellington.events,ellington.podcasts等)

    问题0

    A&#34;模块&#34;在这种情况下,它只是一个由其他应用程序组成的应用程序?

    问题1

    (具有相关功能和共享模型的应用)

    当应用分享模特时,我该怎么办?

    在Barrett的幻灯片中,他暗示用户注册和用户个人资料是截然不同的,应该是不同的应用程序。 (他当然声明配置文件与用户注册无关)。

    所以,如果我想要两者,我的项目会有两个应用程序,如:

    • 用户注册
    • 用户概况

    即使应用user-profile需要user-registration的用户模型?或者我制作一个应用程序(module):

    • 用户应用内
      • 注册
      • 简档

    包含两者?

    问题2

    (具有不同功能但共享模型的应用)

    扩展问题1中的示例,假设我的主应用程序(或主应用程序使用的其他应用程序)利用用户模型的某些方面(例如,如果它是聊天网站,则最近活跃的成员)。 / p>

    显然,我的主应用程序从用户模型中获取此信息。我的主应用程序现在是否捆绑在user-app模块下?

    这可能不是最好的例子,但重点如下:

    我有两个应用app-dependencyapp-needs-dependency,其中每个应用都做了一件事,一件好事......只是app-needs-dependency需要来自app-dependency的信息。在这种情况下,如果关于app-needs-dependency的所有其他内容与app-dependency完全分离(因此可以在其他项目中使用),我该怎么办?

    问题3

    (编写应用程序以获得灵活性)

    现在我的网站上有几个应用程序。每个应用程序都做了一件事,并做得很好。在这种情况下,主应用程序用作登录页面/概述。

    我希望我的所有其他应用程序都使用/继承主应用程序的静态和模板文件。

    我在哪里存储所有静态文件和模板?在主应用程序中并将其设置为其他应用程序的默认值?或者这些静态文件/模板(例如base.cssbase.html)应该放在哪里? 我是否为每个其他应用程序复制这些文件,因此即使这是多余的,也可以运行它们?

    哪个让我的应用更灵活?

3 个答案:

答案 0 :(得分:3)

问题0

Python上下文中的“模块”只是一个包含定义和语句的文件。所以“包下的相关模块”实际上只是意味着“根据代码的作用将代码分成不同的文件”。

将其描述为“由其他应用程序组成的应用程序”是开始将Django的应用程序概念与Python的模块概念混淆(如上所述,它只是包含一些代码的文件)。

问题1

  

当应用分享模特时,我该怎么办?

你仍然应该坚持“应用做一件事,做得好”的格言。在这种情况下,单独的配置文件和注册应用程序似乎是个好主意 - 因为它们具有完全不同的功能注册应用程序将包含允许用户在您的网站上注册的逻辑。配置文件应用程序是关于您将存储的有关用户的信息。

这两个应用程序彼此之间没有任何关系 - 见下文。

问题2

  

假设我的主应用程序(或主应用程序使用的其他应用程序)使用用户模型的某些方面(例如,如果它是聊天网站,则最近活跃的成员)。显然,我的主应用程序从用户模型中获取此信息。我的主应用程序现在是否捆绑在用户应用程序下?

没有。它应该仍然是一个单独的应用程序,带有指向其他应用程序的链接。

用户模型实际上就是一个很好的例子。 Django允许您指定custom user model,以便存储您想要的有关用户的任何其他数据。

现在,有很多第三方应用程序可以为用户执行注册,身份验证等操作。它们设计用于任何用户模型,而不仅仅是Django的默认模型。他们这样做的方法是使用get_user_model()来引用User模型,而不是直接导入django.contrib.auth.models.User

这意味着您可以将这些第三方应用程序用于您为自己的项目定义的任何用户模型。

Django的get_user_model()实用程序用于提供一个非常常见的用例。但是,相同的原则可以扩展到您自己的应用程序。如果您认为应该可以交换的应用程序之间存在依赖关系,那么您可以提供一种交换方式 - 例如,允许使用您的应用程序的任何其他项目指定替代方案的设置/配置。

Django生态系统中有数百种这种可配置性的例子。例如,Django本身附带了自己的django.contrib.auth身份验证应用程序。但是,如果您想要实现自己的身份验证逻辑,则不必再自己重新实现整个身份验证应用程序(这将是一个巨大的痛苦)。而是指定一个authentication backend,它的auth应用程序将用于进行身份验证。 auth应用程序旨在允许任何项目以最小的努力交换其功能的核心部分。

因此,在您的main应用中,您可以定义一个设置来控制要使用的profile模型。这意味着如果其他人想要使用不同的个人资料模型,他们只需更改此设置即可全部设置。它们不再与您的profile应用绑定。

例如 - 假设您有一个main应用,其视图会显示一些用户数据,但也会提供指向其他应用提供的注册视图的链接。您希望其他任何人都能够使用该应用程序,无论他们使用什么注册应用程序。因此,您可以将此视图恢复原状:

main/views.py

from django.contrib.auth import get_user_model
from django.conf import settings
from django.urls import reverse

class UserDetailView(DetailView):

    # First of all, we're using get_user_model so that a project
    # can specify whatever user model it wants, and still use this
    # view.
    model = get_user_model()

    def get_context_data(self, *args, *kwargs):
        ctx = super().get_context_data(*args, **kwargs)
        # We want to add a link to a registration view into this template context.
        # But we want this to be configurable.
        # Your REGISTRATION_URL would be something like 'profile:registration'
        ctx['registration_link'] = reverse(settings.REGISTRATION_URL)
        return ctx

问题3

  

在这种情况下,主应用程序用作着陆页/概述。我希望我的所有其他应用程序都使用/继承主应用程序的静态和模板文件。我在哪里存储所有静态文件和模板?

您应该将模板存储在每个相应的应用中。如果您的主应用程序提供基本模板,那么这些应该存在于主应用程序中。

如果您的个人资料应用随后提供了注册视图,那么该模板应该存在于个人资料应用中。从主应用程序扩展基本模板没有任何问题 - 这可以很容易地被想要的项目覆盖。

可以假设两个应用程序如何相互关联 - 只要您小心允许覆盖这些假设。

答案 1 :(得分:2)

我必须承认你的问题不是技术问题,而是概念问题和教条问题。 没有答案是绝对的,普遍有效的,关于你如何投射结构和应该表现的每一个细节都可以改变观点。 正如您所写,每个Django应用程序都做了一件事,并且做得很好。

我会将其扩展到每个应用程序应该包含不超过一个Model的点,并且最多只能包含壁橱。

Ex: ProductCategoryColorImage

你将有足够的逻辑覆盖那个应用程序内部只有这些。

尝试将Django框架视为创建项目的工具..这是最终目标......但如果您还想创建可重用的应用程序,请尝试尽可能独立创建它们,或者至少依赖于某些Django的特点:

例如:一个可重复使用的应用并且完全独立的应用只需要Django中包含的User模型,SessionsGroups。您可以了解dependent但仍然是自主app。

app毕竟是项目的一部分......无论是在这里还是在构建它之后的其他部分。看它就好像它是一个简单的函数...可以单独运行或者可以依赖于其他函数结果......在什么时候你将所有东西都保存在一个函数中,当你决定将它们分成两个独立的函数时。 所以:

  • 问题0:

    应用程序是可以由它自己运行的最小部分......具有模型,视图,模板,URL,静态文件。

    它也可以依赖于其他应用......所以答案是肯定的

  • 问题1:

    始终将功能分开...... User Auth正在处理用户创建及其身份验证

    用户个人资料正在处理用户的个人数据

  • 问题2:

    没有捆绑任何东西。一切都与2个不同但依赖的应用程序保持同一水平

  • 问题3:

    你可以按照自己的意愿去做。

    您可以将静态作为中心位置和特定于每个应用程序或所有内容的模板。 这里没有正确的答案,只有适合您项目的规模。

答案 2 :(得分:1)

这是一个很好的问题,它涵盖了与我开始使用Django时自问的项目结构相关的所有问题。

问题0:

是的,在这种情况下,模块是一个由多个应用程序组成的应用程序(ellington.events,ellington.podcasts)。

问题1,问题2,问题3:

Django是一个通用的,完整的堆栈Web框架。由于它是通用的,很多都取决于您的特定用例。 您不需要遵循特定结构的整个Django项目(如果您想实现代码重用和功能解耦以及关系解耦)。

话虽如此,如果你可以优先考虑你想要实现的目标,你可以采用一种模式而不是另一种模式。

我们以博客为例。

代码重用:

为了实现最大程度的代码重用,您必须确定项目的哪些部分值得重用。完成后,您可以相应地设置项目结构。

项目结构:

BlogProject

-CommonApps

- AbstractUser(抽象类(就像它的java对应部分))

- AbstractActivity

- AbstractComment

- AbstractArticle

-ProjectApps

- BlogUser(扩展AbstractUser)

- BlogActivity(扩展AbstractActivity)

- BlogComment(扩展AbstractComment)

- BlogArticle(扩展AbstractArticle)

可以在多个项目中共享的功能应该在抽象应用程序中实现,而特定于项目的功能可以在项目应用程序中实现。

关系解耦:

您可以创建应用来表示其他两个应用之间的关系,并实现涉及该关系中两个不同应用的所有功能。

项目结构:

BlogProject

- 用户

-UserActivityRelation

-activity

-Article

-ArticleCommentRelation

-Comment

-UserCommentRelation

- 等等

功能性解耦:

这是最常见的做法 - 为特定功能创建应用程序。

项目结构:

BlogProject

-Article

-activity

- 用户

-Comment

我想在这里提出的观点是,选择权归你所有。在更复杂的项目中,它不会是白色和黑色。

你,取决于&#34; app&#34;对您而言,以及您希望它在特定项目和其他项目中执行的操作,可以决定特定的结构。

Django保持抽象,让你有能力做到这一点。

我总是选择适合该特定项目的应用设置。在项目中所有应用程序都不可重用。在所有情况下,拥有灵活/可重用的应用程序都没有意义。

作为一般的经验法则,Django开发人员说 App 应该是一个功能可以用一个句子描述的东西。但是Django的设计是为了让你可以根据需要改变你的项目规则。

免责声明:功能解耦和关系解耦不是教科书术语。我只是用它们来描述我的意思。