Django 1.6 发行说明 — Django 文档

来自菜鸟教程
Django/docs/2.2.x/releases/1.6
跳转至:导航、​搜索

Django 1.6 发行说明

笔记

献给马尔科姆·特雷丁尼克

2013 年 3 月 17 日,Django 项目和自由软件社区失去了一位非常亲密的朋友和开发人员。

Malcolm 是 Django 的长期贡献者、模范社区成员、聪明的头脑和朋友。 他对 Django 以及许多其他开源项目的贡献几乎无法一一列举。 Django 核心团队中的许多人都由他审查了他们的第一个补丁; 他的指导丰富了我们。 他的体贴、耐心和奉献精神永远激励着我们。

这个版本的 Django 是给 Malcolm 的。

– Django 开发者


2013 年 11 月 6 日

欢迎使用 Django 1.6!

这些发行说明涵盖了 新功能 ,以及从 Django 1.5 或更旧版本升级时您需要注意的一些 向后不兼容更改 。 我们还删除了一些功能,在 我们的弃用计划 中有详细说明,我们已经 开始了一些功能的弃用过程

Python兼容性

Django 1.6 与 Django 1.5 一样,需要 Python 2.6.5 或更高版本。 Python 3 也得到官方支持。 我们 强烈推荐 每个受支持的 Python 系列(2.6.X、2.7.X、3.2.X 和 3.3.X)的最新次要版本。

Django 1.6 将是支持 Python 2.6 的最终发布系列; 从 Django 1.7 开始,支持的最低 Python 版本为 2.7。

不支持 Python 3.4,但将在 Django 1.7 中添加支持。


Django 1.6 中的新功能

简化的默认项目和应用程序模板

:djadmin:`startproject`:djadmin:`startapp` 使用的默认模板已经过简化和现代化。 admin 现在在新项目中默认启用; sites 框架不再是。 点击劫持预防现已开启,数据库默认为SQLite。

如果默认模板不适合您的口味,您可以使用 自定义项目和应用程序模板


改进的事务管理

Django 的事务管理进行了大修。 现在默认启用数据库级自动提交。 这使得事务处理更加明确并且应该提高性能。 如 事务管理文档 中所述,现有 API 已被弃用,并引入了新 API。


持久的数据库连接

Django 现在支持对多个请求重用相同的数据库连接。 这避免了在每个请求开始时重新建立连接的开销。 为了向后兼容,默认情况下禁用此功能。 有关详细信息,请参阅 持久连接


发现任何测试模块中的测试

Django 1.6 附带了一个新的测试运行器,可以在测试位置方面提供更大的灵活性。 前一个运行程序 (django.test.simple.DjangoTestSuiteRunner) 仅在 :setting:`INSTALLED_APPS` 中的 Python 包的 models.pytests.py 模块中找到测试。

新的运行器 (django.test.runner.DiscoverRunner) 使用内置于 unittest2(Python 2.7+ 标准库中的 unittest 版本,并与 Django 捆绑)中的测试发现功能。 通过测试发现,测试可以位于名称与模式 test*.py 匹配的任何模块中。

此外,提供给 ./manage.py test 以指定要运行的特定测试的测试标签现在必须是完整的 Python 虚线路径(或目录路径),而不是 applabel.TestCase.test_method_name 伪路径。 这允许运行位于代码库中任何位置的测试,而不仅仅是在 :setting:`INSTALLED_APPS` 中。 有关更多详细信息,请参阅 在 Django 中进行测试

此更改向后不兼容; 请参阅 向后不兼容说明


时区感知聚合

Django 1.4 中引入的对 时区 的支持不适用于 QuerySet.dates():聚合总是在 UTC 中执行。 这个限制在 Django 1.6 中被取消了。 使用 QuerySet.datetimes()DateTimeField 上执行时区感知聚合。


支持 SQLite 中的保存点

Django 1.6 添加了对 SQLite 中保存点的支持,但有一些 限制


BinaryField 模型字段

新的 django.db.models.BinaryField 模型字段允许在数据库中存储原始二进制数据。


GeoDjango 表单小部件

GeoDjango 现在为其地理专业领域提供 表单字段和小部件 。 默认情况下,它们是基于 OpenLayers 的,但可以自定义它们以使用任何其他 JS 框架。


check管理命令添加验证兼容性

添加了 :djadmin:`check` 管理命令,使您能够验证您当前的配置(当前面向设置)是否与当前版本的 Django 兼容。


Model.save() 算法改变

如果实例具有主键值,Model.save() 方法现在尝试直接 UPDATE 数据库。 以前执行 SELECT 以确定是否需要 UPDATEINSERT。 新算法只需要一个查询来更新现有行,而旧算法需要两个。 有关更多详细信息,请参阅 Model.save()

在极少数情况下,数据库在执行 UPDATE 时不会报告找到匹配的行。 一个例子是 PostgreSQL ON UPDATE 触发器,它返回 NULL。 在这种情况下,可以设置 django.db.models.Options.select_on_save 标志来强制保存使用旧算法。


小功能

  • 身份验证后端可以提升 PermissionDenied 以立即使身份验证链失败。
  • 可以使用 :setting:`CSRF_COOKIE_HTTPONLY` 在 CSRF cookie 上设置 HttpOnly 标志。
  • assertQuerysetEqual() 现在检查未定义的顺序并在发现未定义的顺序时引发 ValueError。 如果给定的 QuerySet 未排序,并且有多个排序值可供比较,则该顺序被视为未定义。
  • 添加 earliest() 以与 latest() 对称。
  • 除了 :lookup:`year`:lookup:`month`:lookup:`day`,ORM 现在支持 : lookup:`hour`, :lookup:`minute`:lookup:`second` 查找。
  • Django 现在包装了所有 PEP-249 异常。
  • EmailFieldURLFieldIntegerFieldFloatFieldDecimalField 的默认小部件使用可用的新类型属性HTML5(type='email'type='url'type='number')。 请注意,由于当前浏览器对带有本地化数字的 number 输入类型的不稳定支持,Django 仅在数字字段未本地化时使用它。
  • 懒惰复数翻译number参数可以在翻译时提供,而不是在定义时提供。
  • 对于自定义管理命令:现在,通过使用 BaseCommand.can_import_settings 内部选项验证命令中是否存在有效设置,独立于在命令执行期间应处于活动状态的区域设置的处理。 后者现在可以受到新的 BaseCommand.leave_locale_alone 内部选项的影响。 有关更多详细信息,请参阅 管理命令和语言环境
  • DeletionMixinsuccess_url 现在与其 object__dict__ 进行插值。
  • HttpResponseRedirectHttpResponsePermanentRedirect 现在提供 url 属性(相当于响应将重定向到的 URL)。
  • MemcachedCache 缓存后端现在使用最新的 pickle 协议。
  • 添加了 SuccessMessageMixin,它为基于 FormView 的类提供 success_message 属性。
  • 添加了 django.db.models.ForeignKey.db_constraintdjango.db.models.ManyToManyField.db_constraint 选项。
  • 嵌入在 admin 中的 jQuery 库已升级到 1.9.1 版。
  • 联合提要 (django.contrib.syndication) 现在可以使用新的 Feed.get_context_data() 回调将额外的上下文传递给提要模板。
  • 管理列表列在 HTML 中有一个 column-<field_name> 类,因此列标题可以使用 CSS 设置样式,例如 设置列宽。
  • 隔离级别可以在PostgreSQL下自定义。
  • :ttag:`blocktrans` 模板标签现在尊重上下文中不存在的变量的 TEMPLATE_STRING_IF_INVALID,就像其他模板结构一样。
  • SimpleLazyObjects 现在将在 shell 调试情况下提供更有用的表示。
  • 通用 GeometryField 现在可以使用管理中的 OpenLayers 小部件进行编辑。
  • 该文档包含一个 部署清单
  • :djadmin:`diffsettings` 命令获得了一个 --all 选项。
  • django.forms.fields.Field.__init__ 现在调用 super(),允许字段 mixin 实现 __init__() 方法,这些方法将被可靠地调用。
  • validate_max 参数已添加到 BaseFormSetformset_factory()ModelForm 及其内联版本。 澄清了 max_num 表单集的验证行为。 以前未记录的强化表单集以抵御内存耗尽攻击的行为已记录,并且未记录的 1000 或 max_num 表单中较高者的限制已更改,因此它始终比 max_num 多 1000。
  • 添加了 BCryptSHA256PasswordHasher 以解决 bcrypt 的密码截断问题。
  • Pillow 现在是与 Django 一起使用的首选图像处理库。 PIL 正在等待弃用(将在 Django 1.8 中删除支持)。 要升级,您应该卸载PIL,然后然后安装Pillow。
  • ModelForm 接受几个新的 Meta 选项。
    • localized_fields 列表中包含的字段将被本地化(通过在表单字段上设置 localize)。
    • labelshelp_textserror_messages 选项可用于自定义默认字段,详情参见 覆盖默认字段
  • 模型字段的 choices 参数现在接受可迭代的迭代,而不是需要可迭代的列表或元组。
  • 可以使用 reason_phrase 在 HTTP 响应中自定义原因短语。
  • 当为 django.contrib.auth.views.logout()django.contrib.auth.views.password_reset()django.contrib.auth.views.password_reset_confirm()django.contrib.auth.views.password_change() 提供下一页的 URL 时,您现在可以传递 URL 名称,它们将被解析。
  • 新的 dumpdata --pks 选项指定要转储的对象的主键。 此选项只能用于一种型号。
  • 添加了 QuerySet 方法 first()last(),它们是返回匹配过滤器的第一个或最后一个对象的便捷方法。 如果没有匹配的对象,则返回 None
  • ViewRedirectView 现在支持 HTTP PATCH 方法。
  • GenericForeignKey 现在采用可选的 for_concrete_model 参数,当设置为 False 时,允许该字段引用代理模型。 默认为 True 以保留旧行为。
  • LocaleMiddleware 现在将活动语言存储在会话中,如果它不存在的话。 这可以防止会话刷新后丢失语言设置,例如 登出。
  • SuspiciousOperation 已被划分为多个子类,每个子类都将记录到 django.security 日志记录层次结构下的匹配命名记录器。 随着这一变化,每当 SuspiciousOperation 到达 WSGI 处理程序以返回 HttpResponseBadRequest 时,都会使用 handler400 机制和默认视图。
  • DoesNotExist 异常现在包含一条消息,指示用于查找的属性的名称。
  • get_or_create() 方法不再需要至少一个关键字参数。
  • SimpleTestCase 类包括一个新的断言助手,用于测试表单集错误:assertFormsetError()
  • 通过 select_related() 添加到 QuerySet 的相关字段列表可以使用 select_related(None) 清除。
  • get_extra()get_max_num() 方法可以覆盖 InlineModelAdmin 以自定义额外和最大内联表单数。
  • Formsets 现在有一个 total_error_count() 方法。
  • ModelForm 字段现在可以通过使用 Field 的构造函数的 error_messages 参数覆盖模型字段中定义的错误消息。 要在自定义字段中利用此新功能, 请参阅更新的建议 以提高 ValidationError
  • ModelAdmin 现在在创建、编辑或删除对象后保留列表视图上的过滤器。 通过将 preserve_filters 属性设置为 False,可以恢复之前清除过滤器的行为。
  • 添加 FormMixin.get_prefix(默认返回 FormMixin.prefix)以允许自定义表单的 prefix
  • 原始查询(Manager.raw()cursor.execute())现在可以使用“pyformat”参数样式,其中查询中的占位符以 '%(name)s' 给出,并且参数作为字典传递而不是比列表(SQLite 除外)。 这在 MySQL 和 PostgreSQL 上早已成为可能(但未得到官方支持),现在也可以在 Oracle 上使用。
  • PBKDF2 密码哈希器的默认迭代次数增加了 20%。 这种向后兼容的更改不会影响现有密码或已将 django.contrib.auth.hashers.PBKDF2PasswordHasher 子类化以更改默认值的用户。 密码 将升级 以根据需要使用新的迭代计数。


1.6 中向后不兼容的更改

警告

除了本节中概述的更改之外,请务必查看 弃用计划 中已删除的任何功能。 如果您尚未在给定功能的弃用时间表内更新代码,则其删除可能会显示为向后不兼容的更改。


新的交易管理模式

行为改变

在 Django 1.6 中默认启用数据库级自动提交。 虽然这不会改变 Django 事务管理的总体精神,但存在一些向后不兼容的问题。


保存点和 assertNumQueries

事务管理中的更改可能会导致创建、释放或回滚保存点的额外语句。 SQLite 更可能发生这种情况,因为它在此版本之前不支持保存点。

如果使用 assertNumQueries() 的测试由于查询数量高于预期而失败,请检查额外的查询是否与保存点相关,并相应地调整预期的查询数量。


PostgreSQL 的自动提交选项

在以前的版本中,数据库级别的自动提交只是 PostgreSQL 的一个选项,默认情况下是禁用的。 这个选项现在被忽略并且可以被删除。


新的测试运行器

为了与 Python 的 unittest 模块保持更大的一致性,新的测试运行器 (django.test.runner.DiscoverRunner) 不会自动支持之前运行器支持的某些类型的测试:

  • models.pytests/__init__.py 文件中的测试将不再被找到和运行。 将它们移动到名称以 test 开头的文件中。
  • Doctests 将不再被自动发现。 要将 doctests 集成到您的测试套件中,请遵循 Python 文档 中的 建议。

Django 捆绑了 Python 标准库中的 doctest 模块的修改版本(在 django.test._doctest 中),并包含一些额外的 doctest 实用程序。 这些实用程序已被弃用,并将在 Django 1.8 中删除; 应该更新 doctest 套件以使用标准库的 doctest 模块(或转换为 unittest 兼容测试)。

如果您希望延迟对测试套件的更新,您可以将 :setting:`TEST_RUNNER` 设置为 django.test.simple.DjangoTestSuiteRunner 以完全恢复旧的测试行为。 DjangoTestSuiteRunner 已弃用,但在 1.8 版之前不会从 Django 中删除。


移除 django.contrib.gis.tests.GeoDjangoTestSuiteRunner GeoDjango 自定义测试运行器

这适用于在 GeoDjango 应用程序本身上工作的开发人员,并与上面有关测试运行程序更改的项目相关:

django.contrib.gis.tests.GeoDjangoTestSuiteRunner 测试运行器已被删除,并且不再支持它实现的独立 GeoDjango 测试执行设置。 要运行 GeoDjango 测试,只需使用新的 DiscoverRunner 并指定 django.contrib.gis 应用程序。


测试中的自定义用户模型

新测试运行器的引入也略微改变了测试模型的导入方式。 因此,任何覆盖 AUTH_USER_MODEL 以使用 Django 的测试用户模型(django.contrib.auth.tests.custom_user.CustomUserdjango.contrib.auth.tests.custom_user.ExtensionUser)之一测试行为的测试现在必须在测试模块中显式导入用户模型:

from django.contrib.auth.tests.custom_user import CustomUser

@override_settings(AUTH_USER_MODEL='auth.CustomUser')
class CustomUserFeatureTests(TestCase):
    def test_something(self):
        # Test code here ...

此导入强制注册自定义用户模型。 如果没有这个导入,测试将无法交换自定义用户模型,你会得到一个错误报告:

ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed

时区感知 day、month 和 week_day 查找

Django 1.6 引入时区支持 :lookup:`day`:lookup:`month`:lookup:`week_day`查找]:setting:`USE_TZ`True。 无论当前时区如何,这些查找以前都是在 UTC 中执行的。

这需要数据库 中的 时区定义。 如果您使用 SQLite,则必须安装 pytz。 如果您使用 MySQL,则必须安装 pytz 并使用 mysql_tzinfo_to_sql 加载时区表。


增加 QuerySet.datetimes()

当 Django 1.4 中添加的 时区支持 [X30X] 处于活动状态时,QuerySet.dates() 查找返回意外结果,因为聚合是在 UTC 中执行的。 为了解决这个问题,Django 1.6 引入了一个新的 API,QuerySet.datetimes()。 这需要对您的代码进行一些更改。

QuerySet.dates() 返回 date 对象

QuerySet.dates() 现在返回 date 的列表。 它用于返回 datetime 的列表。

QuerySet.datetimes() 返回 datetime 的列表。


QuerySet.dates() 在 DateTimeField 上不再可用

QuerySet.dates() 如果在时区支持处于活动状态时将其用于 DateTimeField,则会引发错误。 改用 QuerySet.datetimes()


date_hierarchy 需要时区定义

当在 DateTimeField 上使用时,管理员的 date_hierarchy 功能现在依赖于 QuerySet.datetimes()

:setting:`USE_TZ`True 时,这需要数据库中的时区定义。 了解更多


date_list 在通用视图中需要时区定义

出于同样的原因,当视图基于 DateTimeField:setting 时,在基于日期的通用视图的上下文中访问 date_list 需要数据库中的时区定义: `USE_TZ`True了解更多


新查找可能与模型字段发生冲突

Django 1.6 在 DateTimeField 上引入了 hourminutesecond 查找。 如果您有名为 hourminutesecond 的模型字段,则新查找将与您的字段名称冲突。 如果这是一个问题,请附加一个明确的 :lookup:`exact` 查找。


BooleanField 不再默认为 False

BooleanField 没有显式 default 时,隐式默认值为 None。 在以前的 Django 版本中,它是 False,但这并不能准确表示缺少值。

依赖默认值 False 的代码在将新模型实例保存到数据库时可能会引发异常,因为 None 不是 BooleanField 的可接受值。 您应该在字段定义中指定 default=False,或确保在保存对象之前将该字段设置为 TrueFalse


模板中的翻译和注释

评论后提取翻译

使用 :djadmin:`makemessages` 命令从模板中提取可翻译文字现在可以正确检测 i18n 构造,当它们位于 {# / #} 类型注释之后同一行。 例如:

{# A comment #}{% trans "This literal was incorrectly ignored. Not anymore" %}

译者评论的位置

使用{# / #}指定的模板中的翻译器注释需要在行尾。 如果不是,评论将被忽略并且 :djadmin:`makemessages` 将生成一个警告。 例如:

{# Translators: This is ignored #}{% trans "Translate me" %}
{{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
<h1>{% trans "Welcome" %}</h1>

引用 reverse()

在反转 URL 时,Django 在将参数插入 URL 模式之前不会将 django.utils.http.urlquote 应用于参数。 此错误已在 Django 1.6 中修复。 如果您在将参数传递给 reverse() 之前通过应用 URL 引用来解决此错误,则可能会导致双引号。 如果发生这种情况,只需从代码中删除 URL 引用即可。 您还必须将 assertRedirects() 中使用的 URL 中的特殊字符替换为其编码版本。


在评论应用程序中存储 IP 地址

评论应用程序现在使用 GenericIPAddressField 来存储评论者的 IP 地址,以支持从 IPv6 地址提交的评论。 到目前为止,它将它们存储在 IPAddressField 中,这只是为了支持 IPv4。 保存来自 IPv6 地址的注释时,该地址将在 MySQL 数据库上被静默截断,并在 Oracle 上引发异常。 您将需要更改数据库中的列类型才能从此更改中受益。

对于 MySQL,在您项目的数据库上执行此查询:

ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);

对于 Oracle,执行以下查询:

ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));

如果您不应用此更改,则行为不变:在 MySQL 上,IPv6 地址会被静默截断; 在 Oracle 上,会生成异常。 SQLite 或 PostgreSQL 数据库不需要更改数据库。


cursor.execute 查询中的百分比文字

当您通过 cursor.execute 方法运行原始 SQL 查询时,查询内部的百分比文字 (%) 加倍规则已统一。 过去的行为取决于数据库后端。 现在,在所有后端中,如果您还提供替换参数,则只需要将文字百分比字符加倍。 例如:

# No parameters, no percent doubling
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")

# Parameters passed, non-placeholders have to be doubled
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])

SQLite 用户需要检查和更新此类查询。


ManyToManyField 字段的模型表单字段的帮助文本

对应于 ManyToManyField 模型字段的模型表单字段的 HTML 渲染,用于获取硬编码语句:

在 Mac 上按住“Control”或“Command”可选择多个。


(或其转换为活动区域设置)作为帮助图例显示在它们旁边,如果 modelformhelp_text被附加到提供的任何 help_text)。

由于这发生在模型层,因此无法阻止文本在不适用的情况下出现,例如实现不涉及键盘和/或鼠标的用户交互的表单字段。

从 Django 1.6 开始,作为临时临时向后兼容条款,添加“Hold down...”语句的逻辑已移至模型表单字段层,并修改为仅在关联小部件为 [X235X ]SelectMultiple 或选定的子类。

如果您为 ManyToManyField 模型字段使用自定义模型表单字段和/或小部件,其 UI 确实依赖于上述硬编码句子的自动提供,则更改可能会以向后不兼容的方式影响您。 这些表单字段实现需要通过提供自己对 help_text 属性的处理来适应新的场景。

使用 Django model form 设施以及 Django 内置表单 fieldswidgets 的应用程序不受影响,但需要了解 中描述的内容]下面的 ManyToManyField 字段 的模型表单字段帮助文本的调整。


查询集迭代

QuerySet 迭代已更改为立即将所有获取的行转换为 Model 对象。 在 Django 1.5 及更早版本中,提取的行被转换为 Model 对象,以 100 为一组。

现有代码可以工作,但在某些用例中转换为对象的行数可能会发生变化。 此类用法包括部分循环查询集或任何以 __bool____contains__ 结束的用法。

值得注意的是,大多数数据库后端在 1.5 中已经一次性获取了所有行。

仍然可以通过使用 iterator() 方法将获取的行延迟转换为 Model 对象。


BoundField.label_tag 现在包含表单的 label_suffix

这与 Form.as_pForm.as_ul 等方法渲染标签的方式一致。

如果您在模板中手动渲染 label_tag

{{ form.my_field.label_tag }}: {{ form.my_field }}

您需要删除冒号(或您可能使用的任何其他分隔符)以避免在升级到 Django 1.6 时重复它。 Django 1.6 中的以下模板将呈现与 Django 1.5 中的上述模板相同,除了冒号将出现在 <label> 元素内。

{{ form.my_field.label_tag }} {{ form.my_field }}

将呈现如下内容:

<label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />

如果要保留当前渲染 label_tag 的行为而不使用 label_suffix,请实例化表单 label_suffix=。 您还可以使用 label_tag() 上的新 label_suffix 参数在每个字段的基础上自定义 label_suffix


管理员视图 _changelist_filters GET 参数

为了实现保留和恢复列表视图过滤器,管理视图现在传递 _changelist_filters GET 参数。 如果您有自定义管理模板或者您的测试依赖于以前的 URL,那么您必须考虑到这种更改。 如果您想恢复到原始行为,您可以将 preserve_filters 属性设置为 False


django.contrib.auth 密码重置使用 User PK 的 base 64 编码

过去版本的 Django 在密码重置视图和 URL (django.contrib.auth.views.password_reset_confirm()) 中使用 User 主键的 base 36 编码。 如果用户主键是整数,则 Base 36 编码就足够了,但是,随着 Django 1.5 中自定义用户模型的引入,这种假设可能不再成立。

django.contrib.auth.views.password_reset_confirm() 已修改为采用 uidb64 参数而不是 uidb36。 如果您要反转此视图,例如在自定义 password_reset_email.html 模板中,请务必更新您的代码。

django.contrib.auth.views.password_reset_confirm() 添加了一个临时垫片,允许在 Django 1.6 之前生成的密码重置链接继续工作,以提供向后兼容性; 这将在 Django 1.7 中删除。 因此,只要您的站点运行 Django 1.6 的时间超过 :setting:`PASSWORD_RESET_TIMEOUT_DAYS`,此更改将无效。 如果不是(例如,如果您直接从 Django 1.5 升级到 Django 1.7),那么在升级到 Django 1.7 或更高版本之前生成的任何密码重置链接在升级后都将不起作用。

此外,如果您有任何自定义密码重置 URL,则需要通过将 uidb36 替换为 uidb64 并将该模式后面的破折号替换为斜杠来更新它们。 还将 _\- 添加到可能与 uidb64 模式匹配的字符列表中。

例如:

url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
    'django.contrib.auth.views.password_reset_confirm',
    name='password_reset_confirm'),

变成:

url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
    'django.contrib.auth.views.password_reset_confirm',
    name='password_reset_confirm'),

您可能还想添加垫片以支持旧样式的重置链接。 使用上面的示例,您可以通过将 django.contrib.auth.views.password_reset_confirm 替换为 django.contrib.auth.views.password_reset_confirm_uidb36 并删除 name 参数来修改现有的 url,这样它就不会与新的 url 冲突:

url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
    'django.contrib.auth.views.password_reset_confirm_uidb36'),

在您的应用程序使用 Django 1.6 为 :setting:`PASSWORD_RESET_TIMEOUT_DAYS` 部署后,您可以删除此 URL 模式。


默认会话序列化切换为 JSON

历史上,django.contrib.sessions 使用 pickle 在将会话数据存储到后端之前对其进行序列化。 如果您使用 签名的 cookie 会话后端:setting:`SECRET_KEY` 被攻击者知道(Django 中没有导致其泄漏的固有漏洞) ),攻击者可以在他的会话中插入一个字符串,当它解压时,在服务器上执行任意代码。 这样做的技术很简单,而且很容易在互联网上找到。 尽管 cookie 会话存储对 cookie 存储的数据进行签名以防止篡改,但 :setting:`SECRET_KEY` 泄漏立即升级为远程代码执行漏洞。

这种攻击可以通过使用 JSON 而不是 pickle 序列化会话数据来缓解。 为此,Django 1.5.3 引入了一个新设置 :setting:`SESSION_SERIALIZER`,用于自定义会话序列化格式。 为了向后兼容,此设置在 Django 1.5.3 中默认使用 pickle,但我们在 1.6 中将默认值更改为 JSON。 如果您升级并从 pickle 切换到 JSON,则升级前创建的会话将丢失。 虽然 JSON 序列化不像 pickle 那样支持所有 Python 对象,但我们强烈建议使用 JSON 序列化会话。 在检查您的代码以确定 JSON 序列化是否适用于您的应用程序时,请注意以下事项:

  • JSON 需要字符串键,因此如果您在 request.session 中使用非字符串键,您可能会遇到问题。
  • 通过将 datetime 值传递给 set_expiry() 来设置会话过期将不起作用,因为 datetime 值在 JSON 中不可序列化。 您可以改用整数值。

有关更多详细信息,请参阅 会话序列化 文档。


对象关系映射器更改

Django 1.6 包含对 ORM 的许多更改。 这些变化主要分为三类:

  1. 错误修复(例如 通用关系、查询组合、连接提升和连接修整修复的正确连接子句)
  2. 准备新功能。 例如,ORM 现在已经在内部为多列外键做好了准备。
  3. 一般清理。

这些更改可能会导致一些兼容性问题。 例如,某些查询现在将生成不同的表别名。 这会影响 QuerySet.extra()。 此外,一些查询现在会产生不同的结果。 一个例子是 exclude(condition),其中条件是复杂的(引用 Q 对象 内的多重连接)。 在许多情况下,受影响的查询在 Django 1.5 中没有产生正确的结果,但现在可以了。 不幸的是,也有一些情况会产生不同的结果,但 Django 1.5 和 1.6 都不会产生正确的结果。

最后,对 ORM 内部 API 进行了许多更改。


杂项

  • django.db.models.query.EmptyQuerySet 不能再被实例化 - 它仅可用作标记类,用于检查是否已调用 none()isinstance(qs.none(), EmptyQuerySet)

  • 如果您的 CSS/JavaScript 代码用于按类型访问 HTML 输入小部件,您应该将其检查为 type='text' 小部件现在可能输出为 type='email'type='url' 或 [ X164X] 取决于它们对应的字段类型。

  • 包含占位符的表单字段 error_messages 现在应始终使用命名占位符("Value '%(value)s' is too big" 而不是 "Value '%s' is too big")。 有关占位符名称的详细信息,请参阅相应的字段文档。 1.6 中的更改特别影响 DecimalFieldModelMultipleChoiceField

  • IntegerFieldEmailFieldIPAddressFieldGenericIPAddressField和SlugField[X137]的一些error_messages已经被被抑制是因为它们复制了与字段相关的验证器已经提供的错误消息。

  • 由于表单验证工作流程的变化,TypedChoiceField coerce 方法应始终返回 choices 字段属性中存在的值。 这个限制应该在 Django 1.7 中再次解除。

  • 缓存后端处理超时的方式发生了变化。 显式传入 timeout=None 不再导致使用默认超时。 它现在将设置一个非到期超时。 将 0 传递到 memcache 后端不再使用默认超时,现在将立即设置并过期值。

  • django.contrib.flatpages 应用程序用于设置自定义 HTTP 标头以进行调试。 这个功能没有被记录并且缓存无效,所以它和它的通用实现一起被删除了,之前在 django.core.xheaders 中可用。

  • XViewMiddleware 已从 django.middleware.doc 移至 django.contrib.admindocs.middleware,因为它是 admindocs 的实现细节,已证明一般不可重用。

  • GenericIPAddressField 现在只允许 blank 值,如果 null 值也被允许。 创建 GenericIPAddressField 允许 blank 但不允许 null 将触发模型验证错误,因为 blank 值始终存储为 null . 以前,在不允许 null 的字段中存储 blank 值会在运行时导致数据库异常。

  • 如果在渲染模板时从方法中引发 NoReverseMatch 异常,则它不会被静音。 例如,如果 view_href() 引发 NoReverseMatch模板:Obj.view href 将导致模板渲染失败。 没有变化 :ttag:`{% 网址 %} ` 标签,它会导致模板渲染像往常一样失败NoReverseMatch被提出。

  • django.test.Client.logout() 现在调用 django.contrib.auth.logout() 这将发送 user_logged_out() 信号。

  • 认证视图现在按名称颠倒,而不是它们在django.contrib.auth.views中的位置。 如果您使用的视图没有 name,您应该更新 urlpatterns 以使用 url()name 参数。 例如:

    (r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete')

    变成:

    url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete')
  • RedirectView 现在有一个 pattern_name 属性,它允许它通过反转 URL 来选择目标。

  • 在 Django 1.4 和 1.5 中,无意中将空白字符串视为有效密码。 这意味着 set_password() 会像 set_unusable_password() 那样将空白密码保存为不可用的密码,因此 check_password() 总是返回 False ] 用于空白密码。 此版本已更正此问题:空白密码现在有效。

  • 管理员 changelist_view 之前接受了 pop GET 参数,以表示它将显示在弹出窗口中。 此参数已重命名为 _popup 以与其他管理视图保持一致。 如果自定义模板使用以前的参数名称,则应更新它们。

  • validate_email() 现在接受以 localhost 作为域的电子邮件地址。

  • 新的 makemessages --keep-pot 选项可防止删除在创建 .po 文件之前生成的临时 .pot 文件。

  • 未记录的 django.core.servers.basehttp.WSGIServerException 已被删除。 改用标准库提供的 socket.error。 此更改也在 Django 1.5.5 中发布。

  • django.views.generic.base.RedirectView.get_redirect_url() 的签名已经改变,现在也接受位置参数(*args, **kwargs)。 任何未命名的捕获组现在都将传递给 get_redirect_url(),如果您不更新自定义方法的签名,这可能会导致 TypeError


1.6 中弃用的功能

事务管理 API

事务管理在 Django 1.6 中被彻底改革,当前的 API 已被弃用:

  • django.middleware.transaction.TransactionMiddleware
  • django.db.transaction.autocommit
  • django.db.transaction.commit_on_success
  • django.db.transaction.commit_manually
  • TRANSACTIONS_MANAGED 设置


django.contrib.comments

Django 的评论框架已被弃用,不再受支持。 它将在 Django 1.6 和 1.7 中可用,并在 Django 1.8 中删除。 自定义解决方案或托管产品(如 Disqus)将为大多数用户提供更好的服务。

以前称为 django.contrib.comments 的代码 仍可在外部存储库 中使用。


支持早于 8.4 的 PostgreSQL 版本

PostgreSQL 8.2 的上游支持期于 2011 年 12 月结束,8.3 的上游支持期于 2013 年 2 月结束。 因此,Django 1.6 将 8.4 设置为它正式支持的最低 PostgreSQL 版本。

强烈建议您使用可用的最新版本的 PostgreSQL,因为性能有所改进并利用 PostgreSQL 9.x 中可用的本机流复制。


:ttag:`cycle` 和 :ttag:`firstof` 的变化

模板系统一般都会对所有变量进行转义以避免 XSS 攻击。 然而,由于历史的偶然性,:ttag:`cycle`:ttag:`firstof` 标签按原样呈现它们的参数。

Django 1.6 启动了一个过程来纠正这种不一致。 future 模板库提供了 :ttag:`cycle`:ttag:`firstof` 的替代实现,可以自动转义它们的输入。 如果您使用这些标签,我们鼓励您在模板顶部包含以下行以启用新行为:

{% load cycle from future %}

或者:

{% load firstof from future %}

实现旧行为的标签已被弃用,在 Django 1.8 中,旧行为将被新行为取代。 为确保与未来版本的 Django 兼容,应修改现有模板以使用 future 版本。

如有必要,您可以暂时禁用自动转义标记安全() 或者 :ttag:`{% 自动转义关闭 %} ` .


CACHE_MIDDLEWARE_ANONYMOUS_ONLY 设置

CacheMiddlewareUpdateCacheMiddleware 用于提供一种仅当请求不是由登录用户发出时缓存请求的方法。 这种机制在很大程度上是无效的,因为中间件正确地考虑了 Vary: Cookie HTTP 标头,并且这个标头在各种场合被设置,例如:

  • 访问会话,或
  • 使用默认开启的 CSRF 保护,或
  • 使用设置 cookie 的客户端库,例如 Google Analytics

无论 CACHE_MIDDLEWARE_ANONYMOUS_ONLY 设置如何,这都使缓存在每个会话的基础上有效工作。


_has_changed 小部件上的方法

如果您定义了自己的表单小部件并在小部件上定义了 _has_changed 方法,那么您现在应该在表单字段本身上定义此方法。


module_name 模型 _meta 属性

Model._meta.module_name 更名为 model_name。 尽管是私有 API,但它将通过常规的弃用路径。


get_(add|change|delete)_permission 模型 _meta 方法

Model._meta.get_(add|change|delete)_permission 方法已弃用。 即使它们不是公共 API 的一部分,它们也会通过常规的弃用路径。 您可以将它们替换为 django.contrib.auth.get_permission_codename('action', Model._meta),其中 'action''add''change''delete'


get_query_set 和类似的方法重命名为 get_queryset

返回 QuerySet(例如 Manager.get_query_setModelAdmin.queryset)的方法已重命名为 get_queryset

例如,如果您正在编写一个实现 Manager.get_query_set 方法的库,并且您需要支持旧的 Django 版本,您应该重命名该方法并有条件地添加具有旧名称的别名:

class CustomManager(models.Manager):
    def get_queryset(self):
        pass # ...

    if django.VERSION < (1, 6):
        get_query_set = get_queryset

    # For Django >= 1.6, models.Manager provides a get_query_set fallback
    # that emits a warning when used.

如果你正在编写一个需要调用 get_queryset 方法并且必须支持旧 Django 版本的库,你应该这样写:

get_queryset = (some_manager.get_query_set
                if hasattr(some_manager, 'get_query_set')
                else some_manager.get_queryset)
return get_queryset() # etc

在自定义管理器实现自己的 get_queryset 方法并调用该方法,并且需要使用较旧的 Django 版本和尚未更新的库的一般情况下,定义一个 [ X226X] 方法如下,并在您的经理内部使用:

class YourCustomManager(models.Manager):
    def get_queryset(self):
        return YourCustomQuerySet() # for example

    if django.VERSION < (1, 6):
        get_query_set = get_queryset

    def active(self): # for example
        return self.get_queryset_compat().filter(active=True)

    def get_queryset_compat(self):
        get_queryset = (self.get_query_set
                        if hasattr(self, 'get_query_set')
                        else self.get_queryset)
        return get_queryset()

这有助于最大限度地减少所需的更改,但在可能覆盖 get_query_setget_queryset 的子类(例如 Django 1.5 中的 RelatedManagers)的情况下也能正常工作。


shortcut 视图和 URLconf

shortcut 视图在 1.0 版本发布后不久从 django.views.defaults 移至 django.contrib.contenttypes.views,但旧位置从未被弃用。 这个疏忽在 Django 1.6 中得到纠正,你现在应该使用新的位置。

URLconf django.conf.urls.shortcut 也被弃用。 如果您将它包含在 URLconf 中,只需替换:

(r'^prefix/', include('django.conf.urls.shortcut')),

和:

(r'^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'django.contrib.contenttypes.views.shortcut'),

ModelForm 不带 fields 或 exclude

以前,如果您希望 ModelForm 使用模型上的所有字段,您可以简单地省略 Meta.fields 属性,并且将使用所有字段。

这可能会导致安全问题,其中字段被添加到模型中,并且无意中会自动成为最终用户可编辑的。 在某些情况下,特别是对于布尔字段,这个问题可能完全不可见。 这是质量分配漏洞的一种形式。

出于这个原因,此行为已被弃用,并且强烈建议不要使用 Meta.exclude 选项。 相反,所有打算包含在表单中的字段都应该在 fields 属性中明确列出。

如果此安全问题确实不适用于您的情况,则有一个快捷方式可以明确指示应使用所有字段 - 对 fields 属性使用特殊值 "__all__"

class MyModelForm(ModelForm):
    class Meta:
        fields = "__all__"
        model = MyModel

如果您有只需要在管理员中使用的自定义 ModelForms,还有另一种选择。 管理员有自己的定义字段的方法(fieldsets 等),因此将字段列表添加到 ModelForm 是多余的。 相反,只需省略 ModelFormMeta 内部类,或省略 Meta.model 属性。 由于 ModelAdmin 子类知道它适用于哪个模型,它可以添加必要的属性来派生功能 ModelForm。 此行为也适用于较早的 Django 版本。


UpdateView 和 CreateView 没有明确的字段

通用视图 CreateViewUpdateView,以及从 ModelFormMixin 派生的任何其他东西,都容易受到上一节中描述的安全问题的影响,因为它们可以自动创建一个ModelForm 使用模型的所有字段。

出于这个原因,如果你使用这些视图来编辑模型,你还必须提供 fields 属性(Django 1.6 中的新属性),这是一个模型字段列表,与 的工作方式相同ModelForm Meta.fields 属性。 或者,您可以将 form_class 属性设置为明确定义要使用的字段的 ModelForm。 不推荐定义 UpdateViewCreateView 子类以与模型一起使用但没有明确的字段列表。


修改 ManyToManyField 字段的模型表单字段的帮助文本

不推荐使用标准模型或模型表单字段执行的 ManyToManyField 模型字段的 help_text 属性的所有特殊处理,如上述 模型表单字段的帮助文本中所述的 ManyToManyField 字段 已弃用并将在 Django 1.8 中删除。

这些字段的帮助文本需要由应用程序、自定义表单字段或小部件处理,就像其他模型字段类型一样。