---
title: "Django 1.6 版本发行说明"
version: 5.1
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/5.1/releases/1.6/
canonical: https://djangodocs.dev/zh-hans/5.1/releases/1.6/
---
# Django 1.6 版本发行说明

> **Note**
>
> 献给 Malcolm Tredinnick
>
> 在 2013 年 3 月 17 日，Django 项目和自由软件社区失去了一位非常亲爱的朋友和开发者。
>
> Malcolm 是 Django 的长期贡献者，模范社区成员，一位聪明的人，也是我们的朋友。他对 Django 和其他许多开源项目的贡献几乎无法计数。 Django 核心团队中的许多人都是通过他审查第一批补丁，他的指导使我们受益匪浅。他的关心、耐心和奉献精神将永远激励着我们。
>
> 这个 Django 版本是为了纪念 Malcolm 而发布的。
>
> -- Django 开发者们

*2013 年 11 月 6 日*

欢迎使用 Django 1.6 ！

这些发布说明涵盖了 [新功能](#whats-new-1-6)，以及从 Django 1.5 或更早版本升级时需要注意的一些 [向后不兼容的更改](#backwards-incompatible-1-6)。我们还删除了一些功能，详细信息在 [我们的弃用计划](/zh-hans/5.1/internals/deprecation/#deprecation-removed-in-1-6) 中说明，同时我们已经 [开始了一些功能的弃用过程](#deprecated-features-1-6)。

## Python 兼容性

与 Django 1.5 一样，Django 1.6 需要 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 的新功能有哪些？

### 简化了默认的项目和应用模板

[`startproject`](/zh-hans/5.1/ref/django-admin/#django-admin-startproject) 和 [`startapp`](/zh-hans/5.1/ref/django-admin/#django-admin-startapp) 使用的默认模板已经简化和现代化。新项目默认启用 [admin](/zh-hans/5.1/ref/contrib/admin/)，不再使用 [sites](/zh-hans/5.1/ref/contrib/sites/) 框架。[防止点击劫持](/zh-hans/5.1/ref/clickjacking/#clickjacking-prevention) 现在默认开启，数据库默认为 SQLite。

如果默认模板不符合您的喜好，您可以使用 [自定义项目和应用程序模板](/zh-hans/5.1/ref/django-admin/#custom-app-and-project-templates)。

### 改进了事务管理

Django 的事务管理经过了彻底改进。现在默认情况下已经打开了数据库级别的自动提交。这使得事务处理更加明确，并应该提高性能。现有的 API 已被弃用，并引入了新的 API，详情请参阅 [事务管理文档](/zh-hans/5.1/topics/db/transactions/)。

### 引入了持久性数据库连接

Django 现在支持在多个请求中重复使用同一个数据库连接。这可以避免在每个请求开始时重新建立连接的开销。出于向后兼容性考虑，此功能默认是禁用的。请查看 [持久连接](/zh-hans/5.1/ref/databases/#persistent-database-connections) 以获取详细信息。

### 能够发现任何测试模块中的测试

Django 1.6 提供了一个新的测试运行器，允许更灵活地定位测试。之前的运行器（`django.test.simple.DjangoTestSuiteRunner`）只在 [`INSTALLED_APPS`](/zh-hans/5.1/ref/settings/#std-setting-INSTALLED_APPS) 中的 Python 包的 `models.py` 和 `tests.py` 模块中找到测试。

新的运行器（`django.test.runner.DiscoverRunner`）使用了内置于 `unittest2` 中的测试发现功能（Python 2.7+ 标准库中的 `unittest` 版本，与 Django 捆绑在一起）。使用测试发现，测试可以位于任何模块中，其名称匹配模式 `test*.py`。

此外，提供给 `./manage.py test` 的测试标签，用于指定要运行的特定测试，现在必须是完整的 Python 点路径（或目录路径），而不是伪路径 `applabel.TestCase.test_method_name`。这允许运行位于代码库中任何位置的测试，而不仅仅是 [`INSTALLED_APPS`](/zh-hans/5.1/ref/settings/#std-setting-INSTALLED_APPS) 中的测试。有关更多详细信息，请参阅 [Django 中的测试](/zh-hans/5.1/topics/testing/)。

这个改变是向后不兼容的，请参阅 [向后不兼容的说明](#new-test-runner)。

### 时区感知的聚合

Django 1.4 中引入的对 [时区](/zh-hans/5.1/topics/i18n/timezones/) 的支持在 [`QuerySet.dates()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.dates) 上并不完善：聚合总是在 UTC 中执行。在 Django 1.6 中解除了这个限制。使用 [`QuerySet.datetimes()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.datetimes) 来对 [`DateTimeField`](/zh-hans/5.1/ref/models/fields/#django.db.models.DateTimeField) 进行时区感知的聚合。

### 在 SQLite 中支持保存点（savepoints）

Django 1.6 在 SQLite 中添加了对保存点的支持，但存在一些 [限制](/zh-hans/5.1/topics/db/transactions/#savepoints-in-sqlite)。

### `BinaryField` 模型字段

新的 [`django.db.models.BinaryField`](/zh-hans/5.1/ref/models/fields/#django.db.models.BinaryField) 模型字段允许在数据库中存储原始二进制数据。

### GeoDjango 表单小部件

GeoDjango 现在为其地理专用字段提供了 [表单字段和小部件](/zh-hans/5.1/ref/contrib/gis/forms-api/)。它们默认使用 OpenLayers，但可以自定义为使用任何其他 JavaScript 框架。

### 新增了 `check` 管理命令，用于验证兼容性。

新增了 [`check`](/zh-hans/5.1/ref/django-admin/#django-admin-check) 管理命令，可以用来验证您当前的配置（目前是基于设置）是否与当前版本的 Django 兼容。

### [`Model.save()`](/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save) 算法已更改

[`Model.save()`](/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save) 方法现在会尝试直接执行数据库 `UPDATE` 操作，如果实例具有主键值。以前会执行 `SELECT` 来确定是否需要执行 `UPDATE` 或 `INSERT`。新算法只需要一次查询来更新现有行，而旧算法需要两次。有关更多详细信息，请参阅 [`Model.save()`](/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save)。

在一些罕见的情况下，数据库在执行 `UPDATE` 时可能不会报告找到匹配的行。一个例子是 PostgreSQL 中的 `ON UPDATE` 触发器，它返回 `NULL`。在这种情况下，可以设置 [`django.db.models.Options.select_on_save`](/zh-hans/5.1/ref/models/options/#django.db.models.Options.select_on_save) 标志来强制使用旧算法进行保存。

### 次要特性

- 身份验证后端可以引发 `PermissionDenied` 来立即终止身份验证链。
- 可以使用 [`CSRF_COOKIE_HTTPONLY`](/zh-hans/5.1/ref/settings/#std-setting-CSRF_COOKIE_HTTPONLY) 来在 CSRF Cookie 上设置 `HttpOnly` 标志。
- `assertQuerysetEqual()` 现在检查未定义的排序，并在发现未定义的排序时引发 [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError)。如果给定的 `QuerySet` 没有排序，并且有多个排序值要进行比较，那么排序被视为未定义。
- 新增了 [`earliest()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.earliest)，以与 [`latest()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.latest) 对称。
- 除了 [`year`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-year)、[`month`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-month) 和 [`day`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-day)，ORM 现在还支持 [`hour`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-hour)、[`minute`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-minute) 和 [`second`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-second) 查找。
- Django 现在包装了所有 [**PEP 249**](https://peps.python.org/pep-0249/) 异常。
- [`EmailField`](/zh-hans/5.1/ref/forms/fields/#django.forms.EmailField)、[`URLField`](/zh-hans/5.1/ref/forms/fields/#django.forms.URLField)、[`IntegerField`](/zh-hans/5.1/ref/forms/fields/#django.forms.IntegerField)、[`FloatField`](/zh-hans/5.1/ref/forms/fields/#django.forms.FloatField) 和 [`DecimalField`](/zh-hans/5.1/ref/forms/fields/#django.forms.DecimalField) 的默认小部件现在使用 HTML5 中可用的新类型属性（`type='email'`、`type='url'`、`type='number'`）。请注意，由于当前浏览器中对本地化数字支持不稳定，因此 Django 只在数值字段未本地化时使用 `number` 输入类型。
- 对于 [延迟复数翻译](/zh-hans/5.1/topics/i18n/translation/#lazy-plural-translations)，可以在翻译时提供 `number` 参数，而不是在定义时提供。
- 对于自定义管理命令：在要求使用 `BaseCommand.can_import_settings` 内部选项的命令中，现在独立于处理执行命令期间应处于活动状态的区域设置的验证。后者现在可以受到新的 `BaseCommand.leave_locale_alone` 内部选项的影响。有关更多详细信息，请参阅 管理命令和区域设置。
- [`DeletionMixin`](/zh-hans/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.DeletionMixin) 的 [`success_url`](/zh-hans/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.DeletionMixin.success_url) 现在使用其 `object` 的 `__dict__` 进行插值。
- [`HttpResponseRedirect`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponseRedirect) 和 [`HttpResponsePermanentRedirect`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponsePermanentRedirect) 现在提供了一个 `url` 属性（等同于响应将重定向到的 URL）。
- `MemcachedCache` 缓存后端现在使用了最新可用的 [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle) 协议。
- 新增了 [`SuccessMessageMixin`](/zh-hans/5.1/ref/contrib/messages/#django.contrib.messages.views.SuccessMessageMixin)，它为基于 [`FormView`](/zh-hans/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView) 的类提供了一个 `success_message` 属性。
- 新增了 [`django.db.models.ForeignKey.db_constraint`](/zh-hans/5.1/ref/models/fields/#django.db.models.ForeignKey.db_constraint) 和 [`django.db.models.ManyToManyField.db_constraint`](/zh-hans/5.1/ref/models/fields/#django.db.models.ManyToManyField.db_constraint) 选项。
- jQuery 库嵌入在管理系统中已升级至 1.9.1 版本。
- 现在，通过新的 [`Feed.get_context_data()`](/zh-hans/5.1/ref/contrib/syndication/#django.contrib.syndication.Feed.get_context_data) 回调，订阅源（[`django.contrib.syndication`](/zh-hans/5.1/ref/contrib/syndication/#module-django.contrib.syndication)）可以将额外的上下文传递给订阅源模板。
- 在 HTML 中，管理员列表列具有 `column-<field_name>` 类，因此可以使用 CSS 对列标题进行样式设置，例如设置列宽。
- 在 PostgreSQL 下，可以自定义 [隔离级别](/zh-hans/5.1/ref/databases/#database-isolation-level)。
- [`blocktrans`](/zh-hans/5.1/topics/i18n/translation/#std-templatetag-blocktrans) 模板标签现在像其他模板结构一样，尊重对于上下文中不存在的变量的 `TEMPLATE_STRING_IF_INVALID`。
- 在 shell 调试情况下，`SimpleLazyObject` 现在会提供更有帮助的表示。
- 通用的 [`GeometryField`](/zh-hans/5.1/ref/contrib/gis/model-api/#django.contrib.gis.db.models.GeometryField) 现在可以在管理员中使用 OpenLayers 小部件进行编辑。
- 文档中包含一个 [部署清单](/zh-hans/5.1/howto/deployment/checklist/)。
- [`diffsettings`](/zh-hans/5.1/ref/django-admin/#django-admin-diffsettings) 命令增加了 `--all` 选项。
- `django.forms.fields.Field.__init__` 现在调用了 `super()`，允许字段混合类实现 `__init__()` 方法，并可靠地被调用。
- 在 `BaseFormSet` 和 [`formset_factory()`](/zh-hans/5.1/ref/forms/formsets/#django.forms.formsets.formset_factory) 以及 `ModelForm` 和相应的内联版本中添加了 `validate_max` 参数。对于带有 `max_num` 的表单集的验证行为进行了澄清。之前未记录的行为，以防止内存耗尽攻击的表单集被记录下来，同时未记录的高于 1000 或 `max_num` 的上限已更改，现在它总是比 `max_num` 多 1000。
- 添加了 `BCryptSHA256PasswordHasher` 来解决 bcrypt 密码截断问题。
- [Pillow](https://pypi.org/project/Pillow/) 现在是与 Django 一起使用的首选图像处理库。 [PIL](https://pypi.org/project/PIL/) 已经进入弃用过程（在 Django 1.8 中将删除支持）。要升级，您应该 **首先** 卸载 PIL，**然后** 安装 Pillow。
- [`ModelForm`](/zh-hans/5.1/topics/forms/modelforms/#django.forms.ModelForm) 接受了一些新的 `Meta` 选项。

  - 包含在 `localized_fields` 列表中的字段将会本地化（通过在表单字段上设置 `localize`）。
  - `labels`、`help_texts` 和 `error_messages` 选项可以用来自定义默认字段，请参阅 [覆盖默认字段](/zh-hans/5.1/topics/forms/modelforms/#modelforms-overriding-default-fields) 获取详细信息。
- 模型字段的 `choices` 参数现在接受一个可迭代的可迭代对象，而不是需要一个列表或元组的可迭代对象。
- 可以使用 [`reason_phrase`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponse.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`](/zh-hans/5.1/ref/django-admin/#cmdoption-dumpdata-pks) 选项指定要转储的对象的主键。此选项只能与一个模型一起使用。
- 新增了 `QuerySet` 方法 [`first()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.first) 和 [`last()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.last)，这些是返回与过滤条件匹配的第一个或最后一个对象的便利方法。如果没有匹配的对象，则返回 `None`。
- [`View`](/zh-hans/5.1/ref/class-based-views/base/#django.views.generic.base.View) 和 [`RedirectView`](/zh-hans/5.1/ref/class-based-views/base/#django.views.generic.base.RedirectView) 现在支持 HTTP `PATCH` 方法。
- `GenericForeignKey` 现在接受一个可选的 `for_concrete_model` 参数，当设置为 `False` 时，允许字段引用代理模型。默认值为 `True`，以保留旧的行为。
- [`LocaleMiddleware`](/zh-hans/5.1/ref/middleware/#django.middleware.locale.LocaleMiddleware) 现在如果活动语言不在会话中，则会将其存储在会话中。这可以防止在会话刷新后（例如注销）丢失语言设置。
- [`SuspiciousOperation`](/zh-hans/5.1/ref/exceptions/#django.core.exceptions.SuspiciousOperation) 被细分为多个子类，并且每个子类都会记录到与 `django.security` 日志层次结构下的匹配命名的记录器中。随着这个变化，每当一个 `SuspiciousOperation` 到达 WSGI 处理程序以返回一个 `HttpResponseBadRequest` 时，将使用 `handler400` 机制和默认视图。
- [`DoesNotExist`](/zh-hans/5.1/ref/models/class/#django.db.models.Model.DoesNotExist) 异常现在包含一个消息，指示用于查找的属性的名称。
- [`get_or_create()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.get_or_create) 方法不再需要至少一个关键字参数。
- [`SimpleTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.SimpleTestCase) 类包括一个用于测试表单集错误的新断言助手：`django.test.SimpleTestCase.assertFormsetError()`。
- 通过 [`select_related()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related) 添加到 [`QuerySet`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet) 的相关字段列表可以使用 `select_related(None)` 清除。
- [`InlineModelAdmin`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin) 上的 [`get_extra()`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.get_extra) 和 [`get_max_num()`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.get_max_num) 方法可以被覆盖，以自定义内联表单的额外和最大数量。
- 现在，表单集具有一个 [`total_error_count()`](/zh-hans/5.1/topics/forms/formsets/#django.forms.formsets.BaseFormSet.total_error_count) 方法。
- [`ModelForm`](/zh-hans/5.1/topics/forms/modelforms/#django.forms.ModelForm) 字段现在可以使用 `Field` 构造函数的 [`error_messages`](/zh-hans/5.1/ref/forms/fields/#django.forms.Field.error_messages) 参数覆盖模型字段中定义的错误消息。要利用这个新特性来自定义字段，请参阅 [更新的建议](/zh-hans/5.1/ref/forms/validation/#raising-validation-error) 来引发 `ValidationError`。
- [`ModelAdmin`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin) 在创建、编辑或删除对象后，现在会保留列表视图上的过滤器。可以通过将 [`preserve_filters`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.preserve_filters) 属性设置为 `False` 来恢复以前的清除过滤器的行为。
- 新增了 [`FormMixin.get_prefix`](/zh-hans/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin.get_prefix) （默认返回 [`FormMixin.prefix`](/zh-hans/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin.prefix)），允许自定义表单的 [`prefix`](/zh-hans/5.1/ref/forms/api/#django.forms.Form.prefix)。
- 原始查询（`Manager.raw()` 或 `cursor.execute()`）现在可以使用 "pyformat" 参数样式，其中查询中的占位符以 `'%(name)s'` 形式给出，参数以字典形式传递，而不是列表（在 SQLite 上除外）。在 MySQL 和 PostgreSQL 上早就支持（但未得到官方支持），现在在 Oracle 上也可用。
- PBKDF2 密码哈希器的默认迭代次数增加了 20%。这个向后兼容的更改不会影响现有的密码或已经子类化 `django.contrib.auth.hashers.PBKDF2PasswordHasher` 以更改默认值的用户。必要时，密码将 [被升级](/zh-hans/5.1/topics/auth/passwords/#password-upgrades) 以使用新的迭代次数。

## Django 1.6 中的向后不兼容变更

> **Warning**
>
> 除了本节中概述的更改之外，还请务必查看 [弃用计划](/zh-hans/5.1/internals/deprecation/#deprecation-removed-in-1-6)，以了解已删除的功能。如果在给定功能的弃用时间范围内未更新代码，则其删除可能会显示为不向后兼容的更改。

### 全新的事务管理模型

#### 行为变更

在 Django 1.6 中，默认情况下启用了数据库级别的自动提交。虽然这不会改变 Django 事务管理的一般原则，但会引入一些不兼容性。

#### 保存点和 `assertNumQueries`

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

如果使用 [`assertNumQueries()`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase.assertNumQueries) 的测试因查询次数超过预期而失败，请检查额外的查询是否与保存点相关，并相应地调整预期的查询次数。

#### PostgreSQL 的自动提交选项

在先前版本中，数据库级别的自动提交仅适用于 PostgreSQL，并且默认情况下被禁用。现在该选项被忽略并可以移除。

### 全新的测试运行器

为了与 Python 的 `unittest` 模块保持更一致，新的测试运行器（`django.test.runner.DiscoverRunner`）不会自动支持以前的运行器支持的一些测试类型：

- 不再会查找和运行 `models.py` 和 `tests/__init__.py` 文件中的测试。将它们移到文件名以 `test` 开头的文件中。
- 不再自动发现 doctests。要将 doctests 集成到测试套件中，请遵循 Python 文档中的 [建议](https://docs.python.org/3/library/doctest.html#doctest-unittest-api)。

Django 包含了 Python 标准库中的 [`doctest`](https://docs.python.org/3/library/doctest.html#module-doctest) 模块的修改版本（在 `django.test._doctest` 中），并包含一些额外的 doctest 工具。这些工具已被弃用，并将在 Django 1.8 中删除；doctest 测试套件应该更新以使用标准库的 doctest 模块（或转换为与 `unittest` 兼容的测试）。

如果希望延迟更新测试套件，可以将 [`TEST_RUNNER`](/zh-hans/5.1/ref/settings/#std-setting-TEST_RUNNER) 设置为 `django.test.simple.DjangoTestSuiteRunner`，以完全恢复旧的测试行为。虽然 `DjangoTestSuiteRunner` 已被弃用，但在 Django 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.CustomUser` 和 `django.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
        ...
```

这个导入语句会强制注册自定义用户模型。如果没有这个导入语句，测试将无法切换到自定义用户模型，你将会收到一个错误报告：

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

### 时间区域感知的 `day`、`month` 和 `week_day` 查找

Django 1.6 在 [`USE_TZ`](/zh-hans/5.1/ref/settings/#std-setting-USE_TZ) 为 `True` 时引入了对 [`day`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-day)、[`month`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-month) 和 [`week_day`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-week_day) 查找的时间区域支持。以前，这些查找在不考虑当前时区的情况下都在 UTC 中执行。

这需要数据库中的 [时区定义](/zh-hans/5.1/ref/models/querysets/#database-time-zone-definitions)。如果使用的是 SQLite，你必须安装 [pytz](http://pytz.sourceforge.net/)。如果使用的是 MySQL，你必须安装 [pytz](http://pytz.sourceforge.net/) 并使用 [mysql\_tzinfo\_to\_sql](https://dev.mysql.com/doc/refman/en/mysql-tzinfo-to-sql.html) 加载时区表。

### 添加了 `QuerySet.datetimes()` 方法

当 Django 1.4 中添加的 [时区支持](/zh-hans/5.1/topics/i18n/timezones/) 处于活动状态时，[`QuerySet.dates()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.dates) 查找返回了意外的结果，因为聚合是在 UTC 中执行的。为了解决这个问题，Django 1.6 引入了一个新的 API，[`QuerySet.datetimes()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.datetimes)。这需要在你的代码中进行一些更改。

#### `QuerySet.dates()` 返回的是 `date` 对象

[`QuerySet.dates()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.dates) 现在返回的是 [`date`](https://docs.python.org/3/library/datetime.html#datetime.date) 的列表。它以前返回的是 [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) 的列表。

[`QuerySet.datetimes()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.datetimes) 返回的是 [`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime) 的列表。

#### `QuerySet.dates()` 不再适用于 `DateTimeField`

当时间区域支持处于活动状态时，如果在 [`DateTimeField`](/zh-hans/5.1/ref/models/fields/#django.db.models.DateTimeField) 上使用 [`QuerySet.dates()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.dates) 会引发错误。此时应该使用 [`QuerySet.datetimes()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.datetimes)。

#### `date_hierarchy` 需要时间区域定义

在管理员中使用 [`date_hierarchy`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.date_hierarchy) 特性时，如果它用于 [`DateTimeField`](/zh-hans/5.1/ref/models/fields/#django.db.models.DateTimeField)，现在会依赖于 [`QuerySet.datetimes()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.datetimes)。

这需要在数据库中启用时区定义，当 [`USE_TZ`](/zh-hans/5.1/ref/settings/#std-setting-USE_TZ) 设置为 `True` 时。详细信息请参阅 [了解更多](/zh-hans/5.1/ref/models/querysets/#database-time-zone-definitions)。

#### 在通用视图中使用的 `date_list` 需要时间区域的定义

出于相同的原因，当视图基于 [`DateTimeField`](/zh-hans/5.1/ref/models/fields/#django.db.models.DateTimeField) 且 [`USE_TZ`](/zh-hans/5.1/ref/settings/#std-setting-USE_TZ) 设置为 `True` 时，在日期为基础的通用视图中访问上下文中的 `date_list` 需要数据库中的时间区域定义。详细信息请参阅 [了解更多](/zh-hans/5.1/ref/models/querysets/#database-time-zone-definitions)。

### 新的查找可能与模型字段冲突

Django 1.6 引入了在 [`DateTimeField`](/zh-hans/5.1/ref/models/fields/#django.db.models.DateTimeField) 上的 `hour`、`minute` 和 `second` 查找。如果您的模型字段名为 `hour`、`minute` 或 `second`，新的查找可能会与您的字段名冲突。如果出现此问题，请附加一个明确的 [`exact`](/zh-hans/5.1/ref/models/querysets/#std-fieldlookup-exact) 查找。

### `BooleanField` 不再默认为 `False`

当一个 [`BooleanField`](/zh-hans/5.1/ref/models/fields/#django.db.models.BooleanField) 没有明确的 [`default`](/zh-hans/5.1/ref/models/fields/#django.db.models.Field.default) 时，隐式的默认值是 `None`。在之前的 Django 版本中，默认值是 `False`，但这并没有准确地表示缺少值。

依赖默认值为 `False` 的代码在保存新的模型实例到数据库时可能会引发异常，因为 `None` 不是 [`BooleanField`](/zh-hans/5.1/ref/models/fields/#django.db.models.BooleanField) 的可接受值。您应该在字段定义中明确指定 `default=False`，或者在保存对象之前确保字段被设置为 `True` 或 `False`。

### 模板中的翻译和注释

#### 提取注释后的翻译内容

使用 [`makemessages`](/zh-hans/5.1/ref/django-admin/#django-admin-makemessages) 命令从模板中提取可翻译文字时，现在可以正确检测到位于同一行的 `{#` / `#}` 类型的注释之后的 i18n 构造。例如：

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

#### 翻译者注释的位置

[模板内对翻译的注释](/zh-hans/5.1/topics/i18n/translation/#translator-comments-in-templates) 使用 `{#` / `#}` 指定的注释必须位于一行的末尾。如果不是，这些注释将被忽略，并且 [`makemessages`](/zh-hans/5.1/ref/django-admin/#django-admin-makemessages) 将生成警告。例如：

```html+django
{# 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`。这个 bug 在 Django 1.6 中已经修复。如果你之前通过在将参数传递给 `reverse()` 之前应用 URL 引用来解决这个问题，这可能导致双重引用。如果发生这种情况，请从你的代码中移除 URL 引用。你还需要将在 [`assertRedirects()`](/zh-hans/5.1/topics/testing/tools/#django.test.SimpleTestCase.assertRedirects) 中使用的 URL 中的特殊字符替换为它们的编码版本。

### 在评论应用中存储 IP 地址

评论应用现在使用 `GenericIPAddressField` 来存储评论者的IP地址，以支持从 IPv6 地址提交的评论。直到现在，它们是存储在 `IPAddressField` 中的，这个字段只支持 IPv4。当保存来自 IPv6 地址的评论时，在 MySQL 数据库上，该地址将被静默截断，并在 Oracle 上引发异常。你需要更改数据库中的列类型才能从这个更改中受益。

对于 MySQL，在您的项目数据库上执行以下查询：

```sql
ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);
```

对于 Oracle，请执行以下查询：

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

如果您不应用此更改，行为将保持不变：在 MySQL 上，IPv6 地址会被静默截断；在 Oracle 上，会生成异常。对于 SQLite 或 PostgreSQL 数据库，不需要进行数据库更改。

### 在 `cursor.execute` 查询中的百分比文字面值

当你通过 [cursor.execute](/zh-hans/5.1/topics/db/sql/#executing-custom-sql) 方法运行原始 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 字段的模型表单字段的帮助文本。

HTML 渲染模型表单字段，对应于用于获取硬编码句子的 [`ManyToManyField`](/zh-hans/5.1/ref/models/fields/#django.db.models.ManyToManyField) 模型字段：

> *按住 "Control" 键，或者在 Mac 上按住 "Command" 键，以选择多个选项。*

（或其翻译成活动语言环境的版本）将作为帮助提示显示在它们旁边，如果用户没有指定 [`model`](/zh-hans/5.1/ref/models/fields/#django.db.models.Field.help_text) 或 [`form`](/zh-hans/5.1/ref/forms/fields/#django.forms.Field.help_text) `help_text` 属性（或者该字符串被附加到任何已提供的 `help_text` 中）。

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

从 Django 1.6 开始，作为临时的向后兼容性规定，添加 "按住..." 句子的逻辑已经移动到模型表单字段层，并修改为仅在关联的小部件为 [`SelectMultiple`](/zh-hans/5.1/ref/forms/widgets/#django.forms.SelectMultiple) 或其选定的子类时添加文本。

如果您为依赖于提供的硬编码句子的自动方式的 `ManyToManyField` 模型字段使用自定义模型表单字段和/或小部件，这个变更可以以向后不兼容的方式影响您。这些表单字段实现需要适应新的情况，通过提供自己的处理 `help_text` 属性的方式来处理它。

使用 Django [模型表单](/zh-hans/5.1/topics/forms/modelforms/) 功能以及 Django 内置的表单 [字段](/zh-hans/5.1/ref/forms/fields/) 和 [小部件](/zh-hans/5.1/ref/forms/widgets/) 的应用不受影响，但需要注意下面 [对于 ManyToManyField 字段的模型表单字段的帮助文本的调整](#m2m-help-text-deprecation) 中描述的内容。

### QuerySet 迭代

`QuerySet` 的迭代方式已更改为立即将所有检索到的行转换为 `Model` 对象。在 Django 1.5 及之前，检索到的行是以 100 行为单位转换为 `Model` 对象的。

现有的代码将正常工作，但在某些用例中，转换为对象的行数可能会发生变化。这些用法包括部分遍历查询集或任何最终执行 `__bool__` 或 `__contains__` 操作的用法。

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

仍然可以通过使用 [`iterator()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.iterator) 方法来惰性地将检索到的行转换为 `Model` 对象。

### [`BoundField.label_tag`](/zh-hans/5.1/ref/forms/api/#django.forms.BoundField.label_tag) 现在包括表单的 [`label_suffix`](/zh-hans/5.1/ref/forms/api/#django.forms.Form.label_suffix)

这与 [`Form.as_p`](/zh-hans/5.1/ref/forms/api/#django.forms.Form.as_p) 和 [`Form.as_ul`](/zh-hans/5.1/ref/forms/api/#django.forms.Form.as_ul) 等方法呈现标签的方式保持一致。

如果您在模板中手动呈现 `label_tag`：

```html+django
{{ form.my_field.label_tag }}: {{ form.my_field }}
```

在升级到 Django 1.6 时，你需要移除冒号（或你可能使用的任何其他分隔符），以避免重复。以下 Django 1.6 中的模板与 Django 1.5 中的上述模板渲染效果相同，只是冒号会出现在 `<label>` 元素内部。

```html+django
{{ form.my_field.label_tag }} {{ form.my_field }}
```

将呈现类似于：

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

如果您想保留呈现不带 `label_suffix` 的 `label_tag` 的当前行为，请实例化表单时使用 `label_suffix=''`。您还可以使用 [`label_tag()`](/zh-hans/5.1/ref/forms/api/#django.forms.BoundField.label_tag) 上的新 `label_suffix` 参数来根据每个字段进行自定义。

### 管理员视图 `_changelist_filters` GET 参数

为了保留和恢复列表视图过滤器，管理员视图现在传递 `_changelist_filters` GET 参数。如果您有自定义的管理员模板或者您的测试依赖于以前的URL，请确保考虑到这个变化。如果您想恢复到原始行为，您可以将 [`preserve_filters`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.preserve_filters) 属性设置为 `False`。

### `django.contrib.auth` 密码重置使用了对 `User` 主键（PK）的 Base64 编码。

Django 的过去版本在密码重置视图和URLs（`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` 模板中，请确保更新您的代码。

为了提供向后兼容性，已经添加了一个临时的 shim，用于允许在 Django 1.6 之前生成的密码重置链接继续工作；这将在 Django 1.7 中被移除。因此，只要您的站点在 Django 1.6 上运行的时间超过了 `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",
),
```

您可能还希望添加 shim 来支持旧式的重置链接。使用上面的示例，您可以通过将现有的 URL 中的 `django.contrib.auth.views.password_reset_confirm` 替换为 `django.contrib.auth.views.password_reset_confirm_uidb36`，并删除 `name` 参数，以防止与新的 URL 冲突：

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

在您的应用程序在 Django 1.6 上部署了超过 `PASSWORD_RESET_TIMEOUT_DAYS` 后，您可以删除这个 URL 模式。

### 默认会话序列化方式切换为 JSON

在历史上，[`django.contrib.sessions`](/zh-hans/5.1/topics/http/sessions/#module-django.contrib.sessions) 使用 [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle) 来序列化会话数据，然后将其存储在后端。如果您使用 [签名的 Cookie 会话后端](/zh-hans/5.1/topics/http/sessions/#cookie-session-backend)，并且 [`SECRET_KEY`](/zh-hans/5.1/ref/settings/#std-setting-SECRET_KEY) 已知于攻击者（Django 本身没有固有的漏洞会导致其泄漏），攻击者可以在其会话中插入一个字符串，当反序列化时，会在服务器上执行任意代码。执行此操作的技术非常简单，且在互联网上很容易找到。尽管 Cookie 会话存储使用签名来防止篡改存储在 Cookie 中的数据，但如果 [`SECRET_KEY`](/zh-hans/5.1/ref/settings/#std-setting-SECRET_KEY) 泄漏，会立即升级为远程代码执行漏洞。

这种攻击可以通过使用 JSON 而不是 [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle) 来序列化会话数据来减轻。为了实现这一点，Django 1.5.3 引入了一个新的设置，[`SESSION_SERIALIZER`](/zh-hans/5.1/ref/settings/#std-setting-SESSION_SERIALIZER)，用于自定义会话序列化格式。为了向后兼容，Django 1.5.3 中默认使用 [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle)，但在 1.6 中我们将默认值更改为 JSON。如果您升级并从 pickle 切换到 JSON，升级之前创建的会话将丢失。虽然 JSON 序列化不支持所有像 [`pickle`](https://docs.python.org/3/library/pickle.html#module-pickle) 那样的 Python 对象，但我们强烈建议使用 JSON 序列化的会话。在检查您的代码以确定 JSON 序列化是否适用于您的应用程序时，请注意以下内容：

- JSON 要求使用字符串键，因此如果您在 `request.session` 中使用非字符串键，则可能会遇到问题。
- 通过将 `datetime` 值传递给 [`set_expiry()`](/zh-hans/5.1/topics/http/sessions/#django.contrib.sessions.backends.base.SessionBase.set_expiry) 来设置会话到期时间将不起作用，因为 `datetime` 值在 JSON 中无法序列化。您可以改为使用整数值。

请查看 [会话序列化](/zh-hans/5.1/topics/http/sessions/#session-serialization) 文档以获取更多详细信息。

### 对象关系映射器（ORM）的变更

Django 1.6 包含了许多 ORM 的变更。这些变更主要可以分为三个类别：

1. 错误修复（例如，针对通用关系的正确连接子句、查询合并、连接提升和连接修剪的修复）
2. 为新功能做准备。例如，ORM 现在在内部已准备好支持多列外键。
3. 整体清理

这些变化可能会导致一些兼容性问题。例如，一些查询现在可能会生成不同的表别名。这可能会影响 [`QuerySet.extra()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.extra)。此外，一些查询现在可能会产生不同的结果。一个例子是 [`exclude(condition)`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude)，其中条件比较复杂（引用了 [`Q objects`](/zh-hans/5.1/ref/models/querysets/#django.db.models.Q) 中的多重连接）。在许多情况下，受影响的查询在 Django 1.5 中并没有生成正确的结果，但现在却能够生成正确的结果。不幸的是，还有一些情况会产生不同的结果，但无论是在 Django 1.5 还是在 1.6 中都没有生成正确的结果。

最后，ORM 的内部 API 发生了许多变化

### 杂项

- `django.db.models.query.EmptyQuerySet` 现在不能再实例化了，它只能用作检查是否调用了 [`none()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.none) 的标记类：`isinstance(qs.none(), EmptyQuerySet)`。
- 如果您的 CSS/JavaScript 代码以前根据输入小部件的类型进行访问，您应该进行审查，因为 `type='text'` 的小部件现在可能会根据其对应的字段类型输出为 `type='email'`、`type='url'` 或 `type='number'`。
- 表单字段的 [`error_messages`](/zh-hans/5.1/ref/forms/fields/#django.forms.Field.error_messages) 中包含占位符的错误消息现在应始终使用具名占位符（`"Value '%(value)s' is too big"` 而不是 `"Value '%s' is too big"`）。有关占位符名称的详细信息，请参阅相应的字段文档。1.6 中的更改特别影响到了 [`DecimalField`](/zh-hans/5.1/ref/forms/fields/#django.forms.DecimalField) 和 [`ModelMultipleChoiceField`](/zh-hans/5.1/ref/forms/fields/#django.forms.ModelMultipleChoiceField)。
- 一些针对 [`IntegerField`](/zh-hans/5.1/ref/forms/fields/#django.forms.IntegerField)、[`EmailField`](/zh-hans/5.1/ref/forms/fields/#django.forms.EmailField)、`IPAddressField`、[`GenericIPAddressField`](/zh-hans/5.1/ref/forms/fields/#django.forms.GenericIPAddressField) 和 [`SlugField`](/zh-hans/5.1/ref/forms/fields/#django.forms.SlugField) 的 [`error_messages`](/zh-hans/5.1/ref/forms/fields/#django.forms.Field.error_messages) 已经被抑制，因为它们重复了与字段绑定的验证器已经提供的错误消息。
- 由于表单验证工作流程的更改，[`TypedChoiceField`](/zh-hans/5.1/ref/forms/fields/#django.forms.TypedChoiceField) 的 `coerce` 方法应该始终返回存在于 `choices` 字段属性中的值。这个限制应该在 Django 1.7 中被取消。
- 在缓存后端中，超时处理方式发生了变化。显式传递 `timeout=None` 不再会使用默认超时。现在它将设置一个永不过期的超时。在 memcache 后端中传递 0 不再使用默认超时，而是立即设置并过期值。
- `django.contrib.flatpages` 应用程序曾经为调试目的设置自定义 HTTP 标头。这个功能没有记录在文档中，而且使得缓存失效，因此已经被移除，以及之前在 `django.core.xheaders` 中可用的通用实现也被移除。
- `XViewMiddleware` 已经从 `django.middleware.doc` 移动到 `django.contrib.admindocs.middleware`，因为它是 admindocs 的实现细节，已被证明在一般情况下不可重用。
- [`GenericIPAddressField`](/zh-hans/5.1/ref/models/fields/#django.db.models.GenericIPAddressField) 现在只允许 `blank` 值，如果也允许 `null` 值。如果创建一个 `GenericIPAddressField`，允许 `blank` 但不允许 `null`，将会触发模型验证错误，因为 `blank` 值总是被存储为 `null`。以前，在一个不允许 `null` 的字段中存储一个 `blank` 值会在运行时引发数据库异常。
- 如果在渲染模板时从方法中引发了 `NoReverseMatch` 异常，它将不会被消除。例如，如果 `view_href()` 引发了 `NoReverseMatch`，那么 `{{ obj.view_href }}` 将导致模板渲染失败。对于 [`{% url %}`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-url) 标签没有改变，当引发 `NoReverseMatch` 时，它仍然会导致模板渲染失败。
- [`django.test.Client.logout()`](/zh-hans/5.1/topics/testing/tools/#django.test.Client.logout) 现在调用 [`django.contrib.auth.logout()`](/zh-hans/5.1/topics/auth/default/#django.contrib.auth.logout)，它将发送 [`user_logged_out()`](/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.signals.user_logged_out) 信号。
- [身份验证视图](/zh-hans/5.1/topics/auth/default/#built-in-auth-views) 现在通过名称反转，而不是它们在 `django.contrib.auth.views` 中的位置。如果您在没有 `name` 的情况下使用这些视图，您应该更新您的 `urlpatterns` 使用带有 `name` 参数的 `django.conf.urls.url()`。例如：

  ```
  (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`](/zh-hans/5.1/ref/class-based-views/base/#django.views.generic.base.RedirectView) 现在有一个 `pattern_name` 属性，允许它通过反转 URL 来选择目标。
- 在 Django 1.4 和 1.5 中，空字符串无意中被认为不是有效密码。这意味着 [`set_password()`](/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.models.User.set_password) 会将空密码保存为不可用密码，就像 [`set_unusable_password()`](/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.models.User.set_unusable_password) 一样，因此 [`check_password()`](/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.models.User.check_password) 对于空密码始终返回 `False`。在此版本中已经进行了修正：空密码现在是有效的。
- 管理员 [`changelist_view`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.changelist_view) 以前接受一个 `pop` GET 参数，表示它将显示在弹出窗口中。现在已将此参数重命名为 `_popup`，以使其与其他管理员视图保持一致。如果您的自定义模板使用了以前的参数名称，您应该进行更新。
- [`validate_email()`](/zh-hans/5.1/ref/validators/#django.core.validators.validate_email) 现在接受具有 `localhost` 作为域名的电子邮件地址。
- 新的 [`makemessages --keep-pot`](/zh-hans/5.1/ref/django-admin/#cmdoption-makemessages-keep-pot) 选项防止在创建 `.po` 文件之前删除生成的临时 `.pot` 文件。
- 未记录的 `django.core.servers.basehttp.WSGIServerException` 已被移除。请改用标准库提供的 `socket.error`。这个变化也在 Django 1.5.5 中发布过。
- [`django.views.generic.base.RedirectView.get_redirect_url()`](/zh-hans/5.1/ref/class-based-views/base/#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 中可用的原生流复制功能。

### 对 [`cycle`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-cycle) 和 [`firstof`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-firstof) 的更改

模板系统通常会对所有变量进行转义，以防止 XSS 攻击。然而，由于历史原因，[`cycle`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-cycle) 和 [`firstof`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-firstof) 标签会原样呈现其参数。

Django 1.6 开始了一个过程来纠正这个不一致性。`future` 模板库提供了 [`cycle`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-cycle) 和 [`firstof`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-firstof) 的替代实现，它们会自动转义其输入。如果您使用这些标签，建议在模板顶部包含以下行以启用新的行为：

```html+django
{% load cycle from future %}
```

或：

```html+django
{% load firstof from future %}
```

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

如有必要，您可以使用 [`mark_safe()`](/zh-hans/5.1/ref/utils/#django.utils.safestring.mark_safe) 或 [`{% autoescape off %}`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-autoescape) 来暂时禁用自动转义。

### `CACHE_MIDDLEWARE_ANONYMOUS_ONLY` 设置

`CacheMiddleware` 和 `UpdateCacheMiddleware` 曾经提供了一种只有在请求不是由已登录用户发起时才缓存的方法。这个机制在很大程度上是无效的，因为中间件正确地考虑了 `Vary: Cookie` HTTP 头，而这个头在各种情况下都被设置，比如：

- 访问会话，或者
- 使用默认启用的 CSRF 保护，或者
- 使用客户端库设置了 cookies，比如 。

这使得缓存在每个会话中都能有效地工作，而不受 `CACHE_MIDDLEWARE_ANONYMOUS_ONLY` 设置的影响。

### `SEND_BROKEN_LINK_EMAILS` 设置

[`CommonMiddleware`](/zh-hans/5.1/ref/middleware/#django.middleware.common.CommonMiddleware) 用于在 `SEND_BROKEN_LINK_EMAILS` 设置为 `True` 时通过电子邮件提供损坏链接的基本报告。

由于 [`CommonMiddleware`](/zh-hans/5.1/ref/middleware/#django.middleware.common.CommonMiddleware) 和 [`LocaleMiddleware`](/zh-hans/5.1/ref/middleware/#django.middleware.locale.LocaleMiddleware) 之间存在难以解决的顺序问题，因此这个功能被拆分成了一个新的中间件： [`BrokenLinkEmailsMiddleware`](/zh-hans/5.1/ref/middleware/#django.middleware.common.BrokenLinkEmailsMiddleware)。

如果您依赖于这个功能，应该将 `'django.middleware.common.BrokenLinkEmailsMiddleware'` 添加到您的 `MIDDLEWARE_CLASSES` 设置中，并从您的设置中删除 `SEND_BROKEN_LINK_EMAILS`。

### 对于小部件上的 `_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_set` 或 `ModelAdmin.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 以及尚未更新的库一起使用，定义一个如下的 `get_queryset_compat` 方法并在管理器内部使用它是有用的：

```
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()
```

这有助于最小化所需的更改，同时在子类（例如 Django 1.5 中的 `RelatedManagers`）可能覆盖 `get_query_set` 或 `get_queryset` 的情况下也能正常工作。

### `shortcut` 视图和 URL 配置

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

URL 配置中的 `django.conf.urls.shortcut` 也已被弃用。如果您在 URL 配置中包含它，只需替换为：

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

使用：

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

### 没有指定 `fields` 或 `exclude` 的 `ModelForm`

以前，如果您想要一个 [`ModelForm`](/zh-hans/5.1/topics/forms/modelforms/#django.forms.ModelForm) 使用模型上的所有字段，您可以简单地省略 `Meta.fields` 属性，所有字段都会被使用。

这可能会导致安全问题，其中字段被添加到模型，并且无意中自动变为可由最终用户编辑。在某些情况下，特别是布尔字段的情况下，这个问题可能是完全不可见的。这是一种 [批量赋值漏洞](https://en.wikipedia.org/wiki/Mass_assignment_vulnerability)。

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

如果在您的情况下确实不适用这个安全问题，那么有一种快捷方式可以明确指示使用所有字段 - 使用字段属性的特殊值 `"__all__"`：

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

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

### 没有显式字段的 `UpdateView` 和 `CreateView`

通用视图 [`CreateView`](/zh-hans/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView) 和 [`UpdateView`](/zh-hans/5.1/ref/class-based-views/generic-editing/#django.views.generic.edit.UpdateView)，以及从 [`ModelFormMixin`](/zh-hans/5.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.ModelFormMixin) 派生的任何其他视图，都容易受到上面描述的安全问题的影响，因为它们可以自动创建一个使用模型的所有字段的 `ModelForm`。

因此，如果您使用这些视图来编辑模型，您必须提供 `fields` 属性（在 Django 1.6 中新增），它是一个模型字段的列表，工作方式与 [`ModelForm`](/zh-hans/5.1/topics/forms/modelforms/#django.forms.ModelForm) 的 `Meta.fields` 属性相同。或者，您可以将 `form_class` 属性设置为明确定义要使用的字段的 `ModelForm`。已经弃用了定义用于与模型一起使用但没有显式字段列表的 `UpdateView` 或 `CreateView` 子类。

### 对于 `ManyToManyField` 字段的模型表单字段的帮助文本的调整

所有标准模型字段或模型表单字段对 `ManyToManyField` 模型字段的 `help_text` 属性执行的特殊处理，如上述 [对于 ManyToManyField 字段的模型表单字段的帮助文本。](#m2m-help-text) 中描述的，已经弃用，并将在 Django 1.8 中移除。

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