Django 1.5 发行说明 — Django 文档
Django 1.5 发行说明
2013 年 2 月 26 日
欢迎使用 Django 1.5!
这些发行说明涵盖了 新功能 ,以及从 Django 1.4 或更旧版本升级时您需要注意的一些 向后不兼容更改 。 我们还删除了一些功能,在 我们的弃用计划 中有详细说明,我们已经 开始了一些功能的弃用过程 。
概述
Django 1.5 中最大的新特性是 可配置用户模型 。 在 Django 1.5 之前,想要使用 Django 的身份验证框架 (django.contrib.auth) 的应用程序被迫使用 Django 的“用户”定义。 在 Django 1.5 中,您现在可以将 User
模型换成您自己编写的模型。 这可能是对现有 User
模型的简单扩展——例如,您可以添加 Twitter 或 Facebook ID 字段——或者您可以用完全为您的站点定制的一个完全替换 User
。
Django 1.5 也是第一个支持 Python 3 的版本! 我们将这种支持标记为“实验性”,因为我们还没有认为它可以投入生产,但是您可以开始将应用程序移植到 Python 3。 我们的下一个版本 Django 1.6 将毫无保留地支持 Python 3。
Django 1.5 中其他值得注意的新特性包括:
- 支持保存模型字段的子集调用
save()
。 这有助于高并发操作,并可以提高性能。 - 通过新的 StreamingHttpResponse 响应类更好地 支持流响应 。
- GeoDjango 现在支持 PostGIS 2.0。
- … 和更多; 见下文。
在可能的情况下,我们尝试根据 我们的 API 稳定性策略 以向后兼容的方式引入新功能。 然而,与之前的版本一样,Django 1.5 附带了一些小的 向后不兼容的更改 ; 从以前版本的 Django 升级的人应该仔细阅读该列表。
一个值得注意的弃用功能是转向“新式”:ttag:`url` 标签。 在 Django 1.3 之前,像 {% url myview %}
这样的语法被错误解释(Django 认为 "myview"
是视图的字面名称,而不是名为 myview
的模板变量)。 Django 1.3 及更高版本引入了 {% load url from future %}
语法以引入更正的行为,其中 myview
被视为变量。
这样做的结果是,如果您没有在模板中使用 {% load url from future %}
,则需要将 {% url myview %}
之类的标签更改为 {% url "myview" %}
。 如果您 是 使用 {% load url from future %}
,您可以简单地在 Django 1.5 下删除该行
Python兼容性
Django 1.5 需要 Python 2.6.5 或更高版本,但我们 强烈推荐 Python 2.7.3 或更高版本。 已取消对 Python 2.5 及以下版本的支持。
此更改应仅影响少数 Django 用户,因为当今大多数操作系统供应商都将 Python 2.6 或更高版本作为其默认版本提供。 但是,如果您仍在使用 Python 2.5,则需要坚持使用 Django 1.4,直到您可以升级 Python 版本。 根据 我们的支持政策 ,Django 1.4 将继续获得安全支持,直到 Django 1.6 发布。
Django 1.5 不在 Jython 最终版本上运行,因为 Jython 的最新版本当前不支持 Python 2.6。 但是,Jython 目前确实提供了一个支持 2.7 的 alpha 版本,而 Django 1.5 支持该 alpha 版本。
Python 3 支持
Django 1.5 引入了对 Python 3 的支持 - 特别是 Python 3.2 及更高版本。 这以 单个 代码库的形式出现; 你不需要在 Python 3 上安装不同版本的 Django。 这意味着您可以编写仅针对 Python 2、仅针对 Python 3 或支持两种平台的单个应用程序的应用程序。
但是,我们暂时将此支持标记为“实验性”:尽管通过我们的自动化测试套件对其进行了大量测试,但在实际测试中却很少。 我们已尽最大努力消除错误,但我们不能确定我们涵盖了 Django 的所有可能用途。
Django 的某些功能不可用,因为它们依赖于尚未移植到 Python 3 的第三方软件,包括:
- MySQL 数据库后端(取决于 MySQLdb)
- ImageField(取决于 PIL)
- LiveServerTestCase(依赖于 Selenium WebDriver)
此外,Django 不仅仅是一个网络框架; 它是一个可插拔组件的生态系统。 在这一点上,很少有第三方应用程序被移植到 Python 3,所以现实世界的应用程序不太可能在 Python 3 下满足其所有依赖项。
因此,我们建议不要在 Python 3 下的生产中使用 Django 1.5。 相反,利用这个机会开始将应用程序移植到 Python 3。 如果您是可插拔组件的作者,我们鼓励您立即开始移植。
我们计划在下一个版本 Django 1.6 中为 Python 3 提供一流的、生产就绪的支持。
Django 1.5 中的新功能
可配置的用户模型
在 Django 1.5 中,您现在可以使用自己的模型作为用户相关数据的存储。 如果您的项目需要超过 30 个字符的用户名,或者如果您想以名字/姓氏以外的格式存储用户名,或者您想将自定义配置文件信息放入您的用户对象,您现在可以这样做。
如果您有一个引用 User 模型的第三方可重用应用程序,您可能需要对引用 User 实例的方式进行一些更改。 您还应该记录您的应用程序所依赖的 User 模型的任何特定功能。
有关更多详细信息,请参阅有关自定义用户模型 的 文档。
支持保存模型字段的子集
方法 Model.save() 有一个新的关键字参数 update_fields
。 通过使用此参数,可以仅保存模型字段的选择列表。 出于性能原因或尝试避免覆盖并发更改时,这可能很有用。
延迟实例(由 .only()
或 .defer()
加载的实例)将仅自动保存加载的字段。 如果在加载后手动设置任何字段,该字段也将在保存时更新。
有关更多详细信息,请参阅 Model.save() 文档。
明确支持流响应
在 Django 1.5 之前,可以通过将迭代器传递给 HttpResponse 来创建流响应。 但这是不可靠的:任何访问 content 属性的中间件都会过早地消耗迭代器。
您现在可以使用新的 StreamingHttpResponse 类显式生成流响应。 这个类公开了一个 streaming_content 属性,它是一个迭代器。
由于 StreamingHttpResponse 没有 content
属性,需要访问响应内容的中间件必须测试流响应并做出相应的行为。
检索与代理模型关联的 ContentType 实例
方法 ContentTypeManager.get_for_model() 和 ContentTypeManager.get_for_models() 有一个新的关键字参数——分别是 for_concrete_model
和 for_concrete_models
。 通过使用此参数传递 False
,现在可以检索与代理模型关联的 ContentType。
吉奥姜戈
- LineString 和 MultiLineString GEOS 对象现在支持 interpolate() 和 project() 方法(所谓的线性参考)。
- GEOSGeometry 对象的
wkb
和hex
属性保留 Z 维度。 - 添加了对 PostGIS 2.0 的支持,并删除了对 GDAL < 1.5 的支持。
小功能
Django 1.5 还包括几个值得注意的小改进:
模板引擎现在将
True
、False
和None
解释为相应的 Python 对象。django.utils.timezone 提供了一个帮助程序,用于在时区之间转换有意识的日期时间。 参见 localtime()。
通用视图支持 OPTIONS 请求。
当由 call_command() 中的代码调用时,管理命令不再引发
SystemExit
。 命令引发的任何异常(主要是 CommandError)都会被传播。此外,当您在自定义命令中输出错误或消息时,您现在应该使用
self.stdout.write('message')
和self.stderr.write('error')
(请参阅有关 管理命令输出 的注释)。:djadmin:`dumpdata` 管理命令一次输出一行,防止在转储大型数据集时出现内存不足错误。
在加拿大本地风味中,魁北克的可接受代码中添加了“pq”。 这是一个古老的缩写。
receiver 装饰器现在能够通过提供信号列表连接到多个信号。
在管理员中,您现在可以按用户所属的组过滤用户。
QuerySet.bulk_create() 现在有一个 batch_size 参数。 默认情况下,batch_size 不受限制,但 SQLite 除外,其中单个批处理受到限制,因此每个查询不超过 999 个参数。
:setting:`LOGIN_URL` 和 :setting:`LOGIN_REDIRECT_URL` 设置现在也接受视图函数名称和 命名的 URL 模式 。 这允许您减少配置重复。 更多信息可以在 login_required() 文档中找到。
Django 现在提供了一个 mod_wsgi auth 处理程序 。
QuerySet.delete() 和 Model.delete() 在某些情况下现在可以采用快速路径。 快速路径允许更少的查询和更少的对象提取到内存中。 有关详细信息,请参阅 QuerySet.delete()。
ResolverMatch
的实例作为resolver_match
存储在请求中。默认情况下,当 :setting:`DEBUG` 为
True
时,所有到达django
记录器的日志消息都会发送到控制台(除非您在 中重新定义记录器) ]:setting:`LOGGING` 设置)。使用 RequestContext 时,现在可以通过在模板中使用
{% if 'someapp.someperm' in perms %}
来查找权限。不再需要在根模板目录中有
404.html
和500.html
模板。 当找不到这些模板时,Django 将针对这两种情况输出一些基本的错误消息。 当然,仍然建议提供这些模板作为一种良好的做法,以便向用户呈现漂亮的错误页面。django.contrib.auth 提供了一个新信号,每当用户无法成功登录时就会发出该信号。 见 user_login_failed
新的
loaddata --ignorenonexistent
选项忽略不再存在的字段的数据。assertXMLEqual() 和 assertXMLNotEqual() 新断言允许您在语义级别测试 XML 内容的相等性,而无需关心语法差异(空格、属性顺序等)。
当 REMOTE_USER 标头在同一浏览器会话期间消失时,RemoteUserMiddleware 现在会强制注销。
基于缓存的会话后端 可以将会话数据存储在非默认缓存中。
现在可以在模型上创建多列索引。 阅读 index_together 文档了解更多信息。
在 Django 的日志记录配置期间,启用了详细的弃用警告,并将警告捕获到日志记录系统中。 记录的警告通过
console
日志处理程序路由,默认情况下需要 :setting:`DEBUG` 为 True 才能生成输出。 结果是 DeprecationWarnings 应该像在 Python 版本 < 2.7 中那样在开发环境中打印到控制台。django.contrib.admin.ModelAdmin.message_user() 方法的 API 已修改为接受附加参数,添加类似于 django.contrib.messages.add_message() 的功能。 这对于从管理操作生成错误消息很有用。
由于新的 django.contrib.admin.ModelAdmin.get_list_filter() 方法,现在可以根据请求自定义管理员的列表过滤器。
1.5 中向后不兼容的变化
ALLOWED_HOSTS 生产需要
新的 :setting:`ALLOWED_HOSTS` 设置验证请求的 Host
标头并防止主机中毒攻击。 现在每当 :setting:`DEBUG` 为 False
时都需要此设置,否则 django.http.HttpRequest.get_host() 将引发 SuspiciousOperation[ X164X]。 有关更多详细信息,请参阅 :setting:`完整文档 ` 对于新设置。
抽象模型管理器
抽象模型能够定义自定义管理器,并且该管理器 将被扩展抽象模型 的任何具体模型继承。 但是,如果您尝试使用抽象模型调用管理器上的方法,现在将引发异常。 以前,该调用是被允许的,但一旦尝试进行任何数据库操作就会失败(通常会出现数据库中的“表不存在”错误)。
如果您在使用抽象类调用的管理器上具有功能,则应将该逻辑迁移到抽象类上的 Python staticmethod
或 classmethod
。
基于年存档类的视图中的上下文
为了与其他基于日期的通用视图保持一致,YearArchiveView 现在在上下文中将 year
作为 datetime.date
而不是字符串传递。 如果您在模板中使用 模板:Year
,则必须将其替换为 模板:Year
。
next_year
和 previous_year
也在上下文中添加。 它们是根据 allow_empty
和 allow_future
计算的。
年和月归档类视图中的上下文
YearArchiveView 和 MonthArchiveView 被记录为提供一个 date_list
在上下文中按升序排序,就像它们基于函数的前辈一样,但它实际上是按降序排列的。 在 1.5 中,已恢复记录的顺序。 当您在模板中迭代 [X79X] 时,您可能想要添加(或删除)reversed
关键字:
{% for date in date_list reversed %}
ArchiveIndexView 仍然提供了降序的 date_list
。
HTTP 请求中的非形式数据
request.POST 将不再包含通过 HTTP 请求发布的数据,在标头中具有非特定于表单的内容类型。 在以前的版本中,使用 multipart/form-data
或 application/x-www-form-urlencoded
以外的内容类型发布的数据最终仍会在 request.POST 属性中表示。 希望访问这些情况的原始 POST 数据的开发人员应改用 request.body 属性。
request_finished 信号
Django 曾经在视图函数返回响应后立即发送 request_finished 信号。 这与延迟内容生成的 流响应 的交互很差。
现在在 WSGI 网关完全消耗内容后发送此信号。 如果您在将响应内容发送到客户端之前依赖于被触发的信号,这可能是向后不兼容的。 如果你这样做,你应该考虑使用 中间件 代替。
笔记
一些 WSGI 服务器和中间件在处理请求后并不总是在响应对象上调用 close
,最明显的是 1.2.6 之前的 uWSGI 和 2.0.7 之前的 Sentry 错误报告中间件。 在这些情况下,根本不发送 request_finished
信号。 这可能导致与数据库和内存缓存服务器的空闲连接。
测试客户端中的 OPTIONS、PUT 和 DELETE 请求
与 GET 和 POST 不同,这些 HTTP 方法不是由 Web 浏览器实现的。 相反,它们用于 API,它们以各种格式(例如 JSON 或 XML)传输数据。 由于此类请求可能包含任意数据,因此 Django 不会尝试解码它们的主体。
但是,测试客户端用于为 OPTIONS 和 DELETE 请求(如 GET)构建查询字符串,并为 PUT 请求(如 POST)构建请求正文。 这种编码是任意的,并且与 Django 在接收请求时的行为不一致,因此它在 Django 1.5 中被删除。
如果您在 OPTIONS 或 DELETE 请求中使用 data
参数,则必须将其转换为查询字符串并将其附加到 path
参数。
如果您在没有 content_type
的 PUT 请求中使用 data
参数,则必须在将数据传递给测试客户端之前对数据进行编码,并设置 content_type
参数。
不再使用simplejson的系统版本
如下所述,Django 1.5 弃用 django.utils.simplejson
,转而支持 Python 2.6 的内置 json
模块。 从理论上讲,这种变化是无害的。 不幸的是,由于 simplejson
版本之间的不兼容,在某些情况下可能会引发错误。
Django 1.4 中与 JSON 相关的特性总是使用 django.utils.simplejson
。 这个模块实际上是:
simplejson
的系统版本,如果有的话(即。import simplejson
有效),如果它比 Django 的内置副本更新或者它具有 C 加速,或者- 标准库中的
json
模块,如果它可用(即。 Python 2.6 或更高版本),或 simplejson
2.0.7 版的内置副本。
在 Django 1.5 中,这些功能使用 Python 的 json
模块,该模块基于 simplejson
的 2.0.9 版。
Django 的 2.0.7 版副本和 Python 的 2.0.9 版副本之间没有已知的不兼容性。 但是,simplejson
的其他版本之间存在一些不兼容:
- 虽然
simplejson
API 被记录为总是返回 unicode 字符串,但可选的 C 实现可以返回一个字节字符串。 这已在 Python 2.7 中修复。 simplejson.JSONEncoder
在 2.2 版本中获得了namedtuple_as_object
关键字参数。
有关这些不兼容性的更多信息,请参见 :ticket:`ticket #18023 <18023#comment:10>` .
最终结果是,如果您安装了 simplejson
并且您的代码直接使用 Django 的内部序列化 - 例如 django.core.serializers.json.DjangoJSONEncoder
,从 simplejson
切换到 json
可能会破坏您的代码。 (一般来说,内部结构的更改没有记录;我们在这里做个例外。)
在这一点上,Django 的维护者认为使用标准库中的 json
提供了向后兼容性的最强保证。 他们建议从现在开始使用它。
hasher方法参数的字符串类型
如果您编写了 自定义密码哈希器 ,则您的 encode()
、verify()
或 safe_summary()
方法应接受 Unicode 参数(password
、[ X147X] 或 encoded
)。 如果任何散列方法需要字节串,您可以使用 force_bytes() 实用程序对字符串进行编码。
验证 previous_page_number 和 next_page_number
使用 对象分页 时,Page 对象的 previous_page_number()
和 next_page_number()
方法不会检查返回的数字是否在现有页面范围内。 它现在会检查它并在数字太低或太高时引发 InvalidPage 异常。
PostgreSQL 上自动提交数据库选项的行为已更改
PostgreSQL 的自动提交选项没有像之前宣传的那样工作。 它确实适用于单个事务块,但在离开第一个块后,自动提交行为从未恢复。 此错误现已在 1.5 中修复。 虽然这只是一个错误修复,但如果您将 PostgreSQL 与自动提交选项一起使用,则值得检查您的应用程序行为。
会话未保存在 500 个响应中
如果响应的状态码为 500,Django 的会话中间件将跳过保存会话数据。
管理员登录失败时的电子邮件检查
在 Django 1.5 之前,如果您尝试登录管理界面并错误地使用您的电子邮件地址而不是您的用户名,管理界面将提供警告,告知您的电子邮件地址不是您的用户名。 在 Django 1.5 中,引入 自定义用户模型 需要删除此警告。 这不会改变管理站点的登录行为; 它只影响在一种特定登录失败模式下显示的警告消息。
测试执行的变化
在执行测试时引入了一些更改,这些更改可能与某些测试设置向后不兼容:
django.test.TransactionTestCase 中的数据库刷新
以前,在 TransactionTestCase 中的每次测试运行之前,测试数据库在 之前被截断 。
为了能够以任何顺序运行单元测试并确保它们始终相互隔离,TransactionTestCase 现在将在 每次测试运行后重置数据库 。
不再有隐式数据库序列重置
TransactionTestCase 测试用于自动重置主键序列以及上述数据库刷新操作。
这已被更改,因此不会隐式重置任何序列。 这可能会导致依赖于硬编码主键值的 TransactionTestCase 测试中断。
新的 reset_sequences 属性可用于强制 TransactionTestCase 可能需要它的旧行为。
测试顺序
为了确保所有 TestCase
代码都以干净的数据库开头,现在按以下顺序执行测试:
- 首先,所有单元测试(包括
unittest.TestCase
、SimpleTestCase、TestCase 和 TransactionTestCase)的运行没有特定的顺序保证或强制执行。 - 然后任何其他测试(例如 doctests) 可能会更改数据库而不将其恢复到其原始状态。
这应该不会导致任何问题,除非您有现有的 doctests 假设 TransactionTestCase 较早执行留下一些数据库状态或单元测试依赖于在执行其他测试后保留的某种形式的状态。 此类测试已经非常脆弱,现在必须更改才能独立运行。
cleaned_data 字典为无效形式保留
cleaned_data 字典现在在表单验证后始终存在。 当表单未验证时,它仅包含通过验证的字段。 您应该使用 is_valid() 方法来测试验证是否成功,而不是使用表单上是否存在 cleaned_data 属性。
syncdb 具有多个数据库的行为
syncdb
现在查询数据库路由器以确定是否应在目标数据库中创建内容类型(当启用 contenttypes 时)和权限(当启用 auth 时)。 以前,它在默认数据库中创建它们,即使使用 --database
选项指定了另一个数据库也是如此。
如果您在多个数据库上使用 syncdb
,您应该确保您的路由器只允许将内容类型和权限同步到其中之一。 有关详细信息,请参阅有关具有多个数据库的 contrib 应用程序的 行为 的文档。
XML 反序列化器不会解析带有 DTD 的文档
为了防止暴露于与外部实体引用和实体扩展相关的拒绝服务攻击,XML 模型反序列化器现在拒绝解析包含 DTD(DOCTYPE 定义)的 XML 文档。 由于 XML 序列化器不输出 DTD,这不会影响典型用法,仅在自定义创建的 XML 文档被传递给 Django 的模型反序列化器的情况下。
Formsets 默认 max_num
表单集工厂的 max_num
参数的(默认)值 None
不再默认允许表单集中有任意数量的表单。 相反,为了防止内存耗尽攻击,它现在默认限制为 1000 个表单。 可以通过为 max_num
显式设置更高的值来提高此限制。
杂项
- django.forms.ModelMultipleChoiceField 现在返回一个空的
QuerySet
作为空值而不是一个空列表。 - int_to_base36() 为非整数输入正确地引发
TypeError
而不是ValueError
。 slugify
模板过滤器现在作为标准 Python 函数在 django.utils.text.slugify() 中可用。 同样,remove_tags
在django.utils.html.remove_tags()
处可用。- 默认情况下,上传的文件不再创建为可执行文件。 如果您需要它们是可执行的,请根据您的需要更改 :setting:`FILE_UPLOAD_PERMISSIONS`。 新的默认值为
0o666
(八进制),当前 umask 值首先被屏蔽掉。 - F 表达式 支持按位运算符
&
和|
。 这些运算符现在可以使用.bitand()
和.bitor()
代替。&
和|
的移除是为了与 Q() 表达式 和QuerySet
的组合一致,其中运算符被用作布尔 AND 和 OR运营商。 - 在
filter()
调用中,当 F 表达式 包含跨越多值关系的查找时,它们并不总是重用与同一链上的其他查找相同的关系。 这已更改,现在 F() 表达式将始终使用与同一filter()
调用中的其他查找相同的关系。 - :ttag:`csrf_token` 模板标签不再包含在 div 中。 如果您需要针对 HTML5 之前的严格 DTD 进行 HTML 验证,您应该在页面中围绕它添加一个 div。
- 模板标签库
adminmedia
仅包含已弃用的模板标签{% admin_media_prefix %}
,已被删除。 尝试使用{% load adminmedia %}
加载它会失败。 如果您的模板仍然包含该行,则必须将其删除。 - 由于实施上的疏忽,可以在不启用 django.contrib.sites 的情况下使用 django.contrib.redirects。 这已经不允许了。 如果您使用
django.contrib.redirects
,请确保 :setting:`INSTALLED_APPS` 包含django.contrib.sites
。 - BoundField.label_tag 现在转义其
contents
参数。 为避免 HTML 转义,请在传递参数之前在参数上使用 django.utils.safestring.mark_safe()。 - 访问通过 select_related() 获取的反向一对一关系现在会引发 DoesNotExist 而不是返回
None
。
1.5 中弃用的功能
django.contrib.localflavor
localflavor contrib 应用程序已拆分为单独的包。 在加速弃用后,django.contrib.localflavor
本身将在 Django 1.6 中被删除。
新软件包可在 GitHub 上获得。 核心团队无法长期有效地维护这些包——目前它只跨越十几个国家; 与翻译类似,维护工作将交给感兴趣的社区成员。
django.contrib.markup
标记 contrib 模块已被弃用,并将遵循加速弃用计划。 直接使用 Python 标记库或 3rd 方标记库优于 Django 在框架中维护此功能。
AUTH_PROFILE_MODULE
随着自定义用户模型的引入,不再需要内置机制来存储用户配置文件数据。
您仍然可以定义与 User 模型具有一对一关系的用户配置文件模型 - 事实上,对于许多需要将数据与用户帐户关联的应用程序,这将是一个合适的设计模式。 但是,不应再使用 AUTH_PROFILE_MODULE
设置和用于访问用户配置文件模型的 django.contrib.auth.models.User.get_profile()
方法。
HttpResponse 的流媒体行为
Django 1.5 弃用了通过将迭代器传递给 HttpResponse 来流式传输响应的能力。 如果您依赖此行为,请切换到 StreamingHttpResponse。 请参阅上面的 对流响应的显式支持 。
在 Django 1.7 及更高版本中,迭代器将立即被 HttpResponse 消耗。
django.utils.simplejson
由于 Django 1.5 放弃了对 Python 2.5 的支持,我们现在可以依赖 Python 标准库中提供的 json
模块,因此我们删除了我们自己的 simplejson
副本。 您现在应该导入 json
而不是 django.utils.simplejson
。
不幸的是,由于 simplejson
版本之间的不兼容,此更改可能会产生不需要的副作用 - 请参阅 向后不兼容的更改 部分。 如果您依赖在 simplejson
成为 Python 的 json
后添加的功能,则应明确导入 simplejson
。
django.utils.encoding.StrAndUnicode
django.utils.encoding.StrAndUnicode
混入已被弃用。 定义 __str__
方法并改为应用 python_2_unicode_compatible() 装饰器。
django.utils.itercompat.product
django.utils.itercompat.product
函数已被弃用。 请改用内置的 itertools.product()
。