设计理念

本文档解释了 Django 开发人员在创建该框架时使用的一些基本理念。其目标是解释过去并指导未来。

概述

松散耦合

Django 架构的一个基本目标是松散耦合和紧密内聚。框架的各个层级不应相互“了解”,除非绝对必要。

例如,模板系统不知道网络请求,数据库层不知道数据显示,视图系统也不关心程序员使用哪个模板系统。

尽管 Django 提供了完整的堆栈以方便使用,但只要可能,堆栈的各个部分都是相互独立的。

更少的代码

Django 应用应尽可能少用代码;应避免样板代码。Django 应充分利用 Python 的动态特性,例如内省。

快速开发

21 世纪 Web 框架的意义在于使 Web 开发的繁琐方面变得快速。Django 应该允许进行极其快速的 Web 开发。

不要重复自己 (DRY)

每个不同的概念和/或数据片段都应该只存在于一个地方。冗余是不好的。规范化是好的。

框架应该在合理的范围内,尽可能少地推断尽可能多的信息。

显式优于隐式

这是PEP 20中列出的核心 Python 原则,这意味着 Django 不应该做太多“魔术”。除非有充分的理由,否则不应该发生魔术。只有当魔术创造了其他方法无法实现的巨大便利性,并且它的实现方式不会混淆试图学习如何使用该功能的开发者时,才值得使用魔术。

一致性

框架在所有级别都应保持一致。一致性适用于从低级别(使用的 Python 代码风格)到高级别(使用 Django 的“体验”)的所有方面。

模型

显式优于隐式

字段不应该仅仅根据字段名称来假设某些行为。这需要对系统有太多的了解,并且容易出错。相反,行为应该基于关键字参数,在某些情况下,基于字段的类型。

包含所有相关的领域逻辑

模型应该封装“对象”的各个方面,遵循 Martin Fowler 的活动记录设计模式。

这就是为什么模型表示的数据和关于它的信息(其人类可读名称、默认排序等选项)都在模型类中定义;理解给定模型所需的所有信息都应该存储模型中。

数据库 API

数据库 API 的核心目标是

SQL 效率

它应该尽可能少地执行 SQL 语句,并且应该在内部优化语句。

这就是为什么开发人员需要显式调用save(),而不是框架在幕后默默地保存内容。

这也是select_related() QuerySet 方法存在的原因。对于选择“每个相关对象”的常见情况,它是一个可选的性能增强器。

简洁而强大的语法

数据库 API 应该允许以尽可能少的语法来编写丰富、表达力强的语句。它不应该依赖于导入其他模块或辅助对象。

必要时,应该在幕后自动执行连接。

每个对象都应该能够访问系统范围内的每个相关对象。此访问应该双向工作。

可以选择轻松地使用原始 SQL

数据库 API 应该意识到它是一个捷径,但不一定是最终解决方案。框架应该使编写自定义 SQL 变得很容易——完整的语句,或者只是作为 API 调用的自定义参数的自定义WHERE子句。

URL 设计

松散耦合

Django 应用中的 URL 不应该与底层的 Python 代码耦合。将 URL 绑定到 Python 函数名称是一件糟糕且丑陋的事情。

同样,Django URL 系统应该允许同一应用的 URL 在不同的上下文中有所不同。例如,一个网站可能将故事放在/stories/下,而另一个网站可能使用/news/

无限的灵活性

URL 应该尽可能灵活。任何可以想象到的 URL 设计都应该被允许。

鼓励最佳实践

框架应该使开发人员设计漂亮的 URL 与设计丑陋的 URL 一样容易(甚至更容易)。

应该避免在网页 URL 中使用文件扩展名。

URL 中的逗号应受到严厉惩罚。

明确的 URL

从技术上讲,foo.com/barfoo.com/bar/是两个不同的 URL,搜索引擎机器人(以及一些 Web 流量分析工具)会将它们视为单独的页面。Django 应该努力“规范化”URL,以免搜索引擎机器人感到困惑。

这就是APPEND_SLASH设置背后的原因。

模板系统

将逻辑与展示分离

我们将模板系统视为一种控制展示和与展示相关的逻辑的工具——仅此而已。模板系统不应该支持超出此基本目标的功能。

避免冗余

大多数动态网站使用某种通用的网站设计——通用的页眉、页脚、导航栏等。Django 模板系统应该使存储这些元素在一个地方变得很容易,从而消除重复代码。

这就是模板继承背后的理念。

与 HTML 解耦

模板系统的设计不应使其只能输出 HTML。它应该同样擅长生成其他基于文本的格式,或者只是纯文本。

不应将 XML 用于模板语言

使用 XML 引擎解析模板会在编辑模板时引入一个全新的错误世界——并且会在模板处理中产生不可接受的开销。

假设设计者具有能力

模板系统的设计不应使模板在 Dreamweaver 等所见即所得编辑器中必须显示得很好。这是一个过于严格的限制,并且不允许语法像现在这样好。Django 期望模板作者能够直接编辑 HTML。

显式处理空格

模板系统不应对空格执行魔术操作。如果模板包含空格,则系统应像处理文本一样处理空格——只需显示它。模板标签中不存在的任何空格都应显示。

不要发明编程语言

目标不是发明一种编程语言。目标是仅提供足够的类似编程的功能,例如分支和循环,这对于做出与展示相关的决策至关重要。Django 模板语言 (DTL)旨在避免高级逻辑。

安全

开箱即用的模板系统应禁止包含恶意代码——例如删除数据库记录的命令。

这也是模板系统不允许任意 Python 代码的另一个原因。

可扩展性

模板系统应该认识到高级模板作者可能希望扩展其技术。

这就是自定义模板标签和过滤器背后的理念。

视图

简单性

编写视图应该像编写 Python 函数一样简单。当函数可以做到时,开发人员不应实例化类。

使用请求对象

视图应该能够访问请求对象——一个存储当前请求元数据的对象。该对象应该直接传递给视图函数,而不是视图函数从全局变量中访问请求数据。这使得视图更轻量、更简洁,并且易于通过传入“伪造”的请求对象进行测试。

松散耦合

视图不应该关心开发者使用哪个模板系统——甚至是否使用了模板系统。

区分GET和POST

GET和POST是不同的;开发者应该显式地使用其中一个。框架应该简化GET和POST数据的区分。

缓存框架

Django的缓存框架的核心目标是

更少的代码

缓存应该尽可能快。因此,围绕缓存后端的框架代码应保持绝对最小化,特别是对于get()操作。

一致性

缓存API应该为不同的缓存后端提供一致的接口。

可扩展性

缓存API应该基于开发者的需求在应用层面上可扩展(例如,参见缓存键转换)。

返回顶部