{"title":"设计理念","version":"2.0","locale":"zh-hans","docname":"misc/design-philosophies","url":"/zh-hans/2.0/misc/design-philosophies/","canonical":"https://djangodocs.dev/zh-hans/2.0/misc/design-philosophies/","summary":"本文档解释了 Django 开发人员在开发 Django 时使用的一些基本哲学， 它的目标是解释过去并指导未来 总体 Link to this heading # 松耦合 Link to this heading # Django…","html":"<h1>设计理念<a class=\"heading-anchor\" href=\"#design-philosophies\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>本文档解释了 Django 开发人员在开发 Django 时使用的一些基本哲学， 它的目标是解释过去并指导未来</p>\n<section id=\"overall\">\n<h2>总体<a class=\"heading-anchor\" href=\"#overall\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"loose-coupling\">\n<span id=\"id1\"></span><h3>松耦合<a class=\"heading-anchor\" href=\"#loose-coupling\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-0\">Django 栈的基本目标是降低耦合度同时加强聚合度。框架里的不同层（Layers）不应该知道对方的代码，除非它们确实需要。</p>\n<p>例如，模板系统不需要知道用户的 Web 请求，数据库层不需要了解如果显示数据，而视图并不关心程序员所使用的模板系统。</p>\n<p>尽管为了方便 Django 带有一个完整的堆栈，但堆栈的各个部分尽可能独立于另一个堆栈。</p>\n</section>\n<section id=\"less-code\">\n<span id=\"id2\"></span><h3>更少的代码<a class=\"heading-anchor\" href=\"#less-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django应用的代码应该尽可能地精简，Django应该充分利用Python的动态能力，比如自省机制（introspection）</p>\n</section>\n<section id=\"quick-development\">\n<span id=\"id3\"></span><h3>快速开发<a class=\"heading-anchor\" href=\"#quick-development\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>在 21 世纪，Web 框架的核心一点是让 Web 开发中枯燥的事情处理得更加快速，Django 可以做到快速的 Web 开发。</p>\n</section>\n<section id=\"don-t-repeat-yourself-dry\">\n<span id=\"dry\"></span><h3>不要重复地造轮子 (DRY)<a class=\"heading-anchor\" href=\"#don-t-repeat-yourself-dry\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-1\">每个独特的概念或数据片应该存在且只存在于一个地方。避免冗余，做好标准化。</p>\n<p>合理的框架应该从尽可能少的信息中推断出尽可能多的需求。</p>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">See also</p>\n<p>波特兰模式知识库中关于DRY的讨论</p>\n</aside>\n</section>\n<section id=\"explicit-is-better-than-implicit\">\n<span id=\"id5\"></span><h3>明确优于隐式<a class=\"heading-anchor\" href=\"#explicit-is-better-than-implicit\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>这是在 <span class=\"target\" id=\"index-6\"></span><a class=\"pep reference external\" href=\"https://peps.python.org/pep-0020/\"><strong>PEP 20</strong></a> 列出的核心 Python 原则，这意味着 Django 不应该使用太多的“魔术”。除非有一个很好的理由，否则不应该出现魔术。只有当魔术创造了巨大的便利，并且使用其他方式难以实现时，它才值得使用，而且它的实现方式并不会让试图学习如何使用该功能的开发人员感到困惑。</p>\n</section>\n<section id=\"consistency\">\n<span id=\"id6\"></span><h3>一致性<a class=\"heading-anchor\" href=\"#consistency\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>框架应在所有层级上保持一致。一致性适用于从低级（Python 的编码风格）到高级（使用 Django 的“经验”）的所有内容。</p>\n</section>\n</section>\n<section id=\"models\">\n<h2>模型<a class=\"heading-anchor\" href=\"#models\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"id7\">\n<h3>明确优于隐式<a class=\"heading-anchor\" href=\"#id7\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>字段不应该仅仅根据字段的名称来假定某些行为。这需要对系统有太多了解，并且容易出现错误。相反，其行为应该基于关键字参数，并且在某些情况下，应该基于字段的类型。</p>\n</section>\n<section id=\"include-all-relevant-domain-logic\">\n<h3>包括所有相关领域逻辑<a class=\"heading-anchor\" href=\"#include-all-relevant-domain-logic\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>模型应该封装一个“对象”的各个方面，遵循 Martin Fowler 的“Active Record”设计模式。</p>\n<p>这就是为什么在模型类中要同时定义一个模型表现的数据以及关于它的信息（其人类可读的名称，默认排序等选项）；所有用于理解给定模型所需的信息都应该存储在模型中。</p>\n</section>\n</section>\n<section id=\"database-api\">\n<h2>数据库API<a class=\"heading-anchor\" href=\"#database-api\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>数据库API的主要用处：</p>\n<section id=\"sql-efficiency\">\n<h3>SQL效率<a class=\"heading-anchor\" href=\"#sql-efficiency\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>它应该尽可能少地执行SQL语句，并且应该在内部优化语句。</p>\n<p>这就是为什么开发者需要显式地调用“save()”，而不是由框架静默地在幕后保存东西。</p>\n<p>这也是为什么“select_related()”“QuerySet”方法存在的原因。在查询“每个关联的对象”的常见情况下，它是一个可选的性能提升器。</p>\n</section>\n<section id=\"terse-powerful-syntax\">\n<h3>简洁, 强大的语法<a class=\"heading-anchor\" href=\"#terse-powerful-syntax\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>数据库 API 应该允许用尽可能少的语法，来表达丰富、达意的语句。它不应该依赖于导入其他模块或辅助对象。</p>\n<p>当必要时, 在幕后插入应该是自动进行的.</p>\n<p>每一个对象都应该能够访问所有相关的目的, 系统范围. 这种访问应该是双向的.</p>\n</section>\n<section id=\"option-to-drop-into-raw-sql-easily-when-needed\">\n<h3>当有必要时, 可方便地选择使用原始 SQL 语句<a class=\"heading-anchor\" href=\"#option-to-drop-into-raw-sql-easily-when-needed\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>应该认识到数据库 API 只是一个便捷的方法，但并不必须是最终的全部手段。框架应该可以很容易地编写自定义的 SQL——完整的语句，或者仅仅是自定义“WHERE”子句作为 API 调用时的自定义参数。</p>\n</section>\n</section>\n<section id=\"url-design\">\n<h2>URL 设计<a class=\"heading-anchor\" href=\"#url-design\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"id8\">\n<h3>松耦合<a class=\"heading-anchor\" href=\"#id8\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 应用中的 URL 不应该与底层 Python 代码耦合。将 URL 与 Python 函数名联系起来是一件很糟糕且丑陋的做法。</p>\n<p>按照这些方法，Django URL 系统应该允许同一应用的 URL 在不同的上下文中有所不同。例如，一个网站可以在“/stories/”中放置故事，而另一个网站则可以使用“/news/”。</p>\n</section>\n<section id=\"infinite-flexibility\">\n<h3>无限的灵活性<a class=\"heading-anchor\" href=\"#infinite-flexibility\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>URL 应该尽可能灵活。任何可想到的 URL 设计都应该被允许。</p>\n</section>\n<section id=\"encourage-best-practices\">\n<h3>鼓励最佳实践<a class=\"heading-anchor\" href=\"#encourage-best-practices\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>框架可以做到让开发者简单（或更加简单）地设计出漂亮的，而不是难看的 URL。</p>\n<p>在 URL 中应避免出现文件后缀名。</p>\n<p>在 URL 中使用 Vignette 式的逗号应该受到严厉的惩罚。</p>\n</section>\n<section id=\"definitive-urls\">\n<span id=\"id9\"></span><h3>定义URL<a class=\"heading-anchor\" href=\"#definitive-urls\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-3\">技术上，<code class=\"docutils literal notranslate\"><span class=\"pre\">foo.com/bar</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">foo.com/bar/</span></code> 是两条不同的 URL，搜索引擎爬虫（以及某些 Web 流量分析工具）会将其视为独立的页面。Django 会将其转为 &quot;标准&quot; 的 URL，让搜索引擎爬虫正确识别。</p>\n<p>详细请参考：setting:APPEND_SLASH setting.</p>\n</section>\n</section>\n<section id=\"template-system\">\n<h2>模板系统<a class=\"heading-anchor\" href=\"#template-system\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"separate-logic-from-presentation\">\n<span id=\"separation-of-logic-and-presentation\"></span><h3>演示不同的逻辑<a class=\"heading-anchor\" href=\"#separate-logic-from-presentation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>We see a template system as a tool that controls presentation and\npresentation-related logic -- and that's it. The template system shouldn't\nsupport functionality that goes beyond this basic goal.</p>\n</section>\n<section id=\"discourage-redundancy\">\n<h3>避免冗余<a class=\"heading-anchor\" href=\"#discourage-redundancy\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The majority of dynamic websites use some sort of common sitewide design --\na common header, footer, navigation bar, etc. The Django template system should\nmake it easy to store those elements in a single place, eliminating duplicate\ncode.</p>\n<p>This is the philosophy behind <a class=\"reference internal\" href=\"/zh-hans/2.0/ref/templates/language/#template-inheritance\"><span class=\"std std-ref\">template inheritance</span></a>.</p>\n</section>\n<section id=\"be-decoupled-from-html\">\n<h3>从 HTML 中解耦<a class=\"heading-anchor\" href=\"#be-decoupled-from-html\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system shouldn't be designed so that it only outputs HTML. It\nshould be equally good at generating other text-based formats, or just plain\ntext.</p>\n</section>\n<section id=\"xml-should-not-be-used-for-template-languages\">\n<h3>XML不应被用于模板语言<a class=\"heading-anchor\" href=\"#xml-should-not-be-used-for-template-languages\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p id=\"index-4\">Using an XML engine to parse templates introduces a whole new world of human\nerror in editing templates -- and incurs an unacceptable level of overhead in\ntemplate processing.</p>\n</section>\n<section id=\"assume-designer-competence\">\n<h3>假设设计能力<a class=\"heading-anchor\" href=\"#assume-designer-competence\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system shouldn't be designed so that templates necessarily are\ndisplayed nicely in WYSIWYG editors such as Dreamweaver. That is too severe of\na limitation and wouldn't allow the syntax to be as nice as it is. Django\nexpects template authors are comfortable editing HTML directly.</p>\n</section>\n<section id=\"treat-whitespace-obviously\">\n<h3>对待空格很明显<a class=\"heading-anchor\" href=\"#treat-whitespace-obviously\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The template system shouldn't do magic things with whitespace. If a template\nincludes whitespace, the system should treat the whitespace as it treats text\n-- just display it. Any whitespace that's not in a template tag should be\ndisplayed.</p>\n</section>\n<section id=\"don-t-invent-a-programming-language\">\n<h3>不要发明一种编程语言<a class=\"heading-anchor\" href=\"#don-t-invent-a-programming-language\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The goal is not to invent a programming language. The goal is to offer just\nenough programming-esque functionality, such as branching and looping, that is\nessential for making presentation-related decisions. The <a class=\"reference internal\" href=\"/zh-hans/2.0/topics/templates/#template-language-intro\"><span class=\"std std-ref\">Django Template\nLanguage (DTL)</span></a> aims to avoid advanced logic.</p>\n<p>The Django template system recognizes that templates are most often written by\n<em>designers</em>, not <em>programmers</em>, and therefore should not assume Python\nknowledge.</p>\n</section>\n<section id=\"safety-and-security\">\n<h3>安全与保障<a class=\"heading-anchor\" href=\"#safety-and-security\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>开箱即用的模板系统禁止包含恶意代码，例如删除数据库记录的代码。</p>\n<p>这就是模板系统不允许有任意Python代码的另一个原因。</p>\n</section>\n<section id=\"extensibility\">\n<h3>可扩展性<a class=\"heading-anchor\" href=\"#extensibility\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>模板系统应该认识到, 高阶的模板作者可能想扩展它.</p>\n<p>这是自定义的模板标签和过滤器背后的理念.</p>\n</section>\n</section>\n<section id=\"views\">\n<h2>视图<a class=\"heading-anchor\" href=\"#views\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"simplicity\">\n<h3>简洁<a class=\"heading-anchor\" href=\"#simplicity\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>编写视图应该和编写Python函数一样简单。开发人员不应该在函数执行时实例化一个类。</p>\n</section>\n<section id=\"use-request-objects\">\n<h3>使用请求对象<a class=\"heading-anchor\" href=\"#use-request-objects\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Views should have access to a request object -- an object that stores metadata\nabout the current request. The object should be passed directly to a view\nfunction, rather than the view function having to access the request data from\na global variable. This makes it light, clean and easy to test views by passing\nin &quot;fake&quot; request objects.</p>\n</section>\n<section id=\"id10\">\n<h3>松耦合<a class=\"heading-anchor\" href=\"#id10\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>视图不应该关心开发人员使用哪种模板——甚至根本不用模板系统。</p>\n</section>\n<section id=\"differentiate-between-get-and-post\">\n<h3>GET方法和POST方法的区别<a class=\"heading-anchor\" href=\"#differentiate-between-get-and-post\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>GET and POST are distinct; developers should explicitly use one or the other.\nThe framework should make it easy to distinguish between GET and POST data.</p>\n</section>\n</section>\n<section id=\"cache-framework\">\n<span id=\"cache-design-philosophy\"></span><h2>缓存框架<a class=\"heading-anchor\" href=\"#cache-framework\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The core goals of Django's <a class=\"reference internal\" href=\"/zh-hans/2.0/topics/cache/\"><span class=\"doc\">cache framework</span></a> are:</p>\n<section id=\"id11\">\n<h3>更少的代码<a class=\"heading-anchor\" href=\"#id11\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>A cache should be as fast as possible.  Hence, all framework code surrounding\nthe cache backend should be kept to the absolute minimum, especially for\n<code class=\"docutils literal notranslate\"><span class=\"pre\">get()</span></code> operations.</p>\n</section>\n<section id=\"id12\">\n<h3>一致性<a class=\"heading-anchor\" href=\"#id12\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The cache API should provide a consistent interface across the different\ncache backends.</p>\n</section>\n<section id=\"id13\">\n<h3>可扩展性<a class=\"heading-anchor\" href=\"#id13\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The cache API should be extensible at the application level based on the\ndeveloper's needs (for example, see <a class=\"reference internal\" href=\"/zh-hans/2.0/topics/cache/#cache-key-transformation\"><span class=\"std std-ref\">Cache key transformation</span></a>).</p>\n</section>\n</section>","rootId":"design-philosophies","toc":[{"title":"总体","anchor":"overall","children":[{"title":"松耦合","anchor":"loose-coupling","children":[]},{"title":"更少的代码","anchor":"less-code","children":[]},{"title":"快速开发","anchor":"quick-development","children":[]},{"title":"不要重复地造轮子 (DRY)","anchor":"don-t-repeat-yourself-dry","children":[]},{"title":"明确优于隐式","anchor":"explicit-is-better-than-implicit","children":[]},{"title":"一致性","anchor":"consistency","children":[]}]},{"title":"模型","anchor":"models","children":[{"title":"明确优于隐式","anchor":"id7","children":[]},{"title":"包括所有相关领域逻辑","anchor":"include-all-relevant-domain-logic","children":[]}]},{"title":"数据库API","anchor":"database-api","children":[{"title":"SQL效率","anchor":"sql-efficiency","children":[]},{"title":"简洁, 强大的语法","anchor":"terse-powerful-syntax","children":[]},{"title":"当有必要时, 可方便地选择使用原始 SQL 语句","anchor":"option-to-drop-into-raw-sql-easily-when-needed","children":[]}]},{"title":"URL 设计","anchor":"url-design","children":[{"title":"松耦合","anchor":"id8","children":[]},{"title":"无限的灵活性","anchor":"infinite-flexibility","children":[]},{"title":"鼓励最佳实践","anchor":"encourage-best-practices","children":[]},{"title":"定义URL","anchor":"definitive-urls","children":[]}]},{"title":"模板系统","anchor":"template-system","children":[{"title":"演示不同的逻辑","anchor":"separate-logic-from-presentation","children":[]},{"title":"避免冗余","anchor":"discourage-redundancy","children":[]},{"title":"从 HTML 中解耦","anchor":"be-decoupled-from-html","children":[]},{"title":"XML不应被用于模板语言","anchor":"xml-should-not-be-used-for-template-languages","children":[]},{"title":"假设设计能力","anchor":"assume-designer-competence","children":[]},{"title":"对待空格很明显","anchor":"treat-whitespace-obviously","children":[]},{"title":"不要发明一种编程语言","anchor":"don-t-invent-a-programming-language","children":[]},{"title":"安全与保障","anchor":"safety-and-security","children":[]},{"title":"可扩展性","anchor":"extensibility","children":[]}]},{"title":"视图","anchor":"views","children":[{"title":"简洁","anchor":"simplicity","children":[]},{"title":"使用请求对象","anchor":"use-request-objects","children":[]},{"title":"松耦合","anchor":"id10","children":[]},{"title":"GET方法和POST方法的区别","anchor":"differentiate-between-get-and-post","children":[]}]},{"title":"缓存框架","anchor":"cache-framework","children":[{"title":"更少的代码","anchor":"id11","children":[]},{"title":"一致性","anchor":"id12","children":[]},{"title":"可扩展性","anchor":"id13","children":[]}]}],"breadcrumbs":[{"docname":"misc/index","title":"元文件和杂记","url":"/zh-hans/2.0/misc/"}],"prev":{"docname":"misc/api-stability","title":"API 的稳定性","url":"/zh-hans/2.0/misc/api-stability/"},"next":{"docname":"misc/distributions","title":"Django 的第三方发布包","url":"/zh-hans/2.0/misc/distributions/"},"formats":{"html":"/zh-hans/2.0/misc/design-philosophies/","markdown":"/zh-hans/2.0/misc/design-philosophies.md","json":"/zh-hans/2.0/misc/design-philosophies.json"},"source":"https://github.com/django/django/blob/stable/2.0.x/docs/misc/design-philosophies.txt","official":"https://docs.djangoproject.com/zh-hans/2.0/misc/design-philosophies/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}