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

*2013 年 2 月 26 日*

欢迎来到 Django 1.5 ！

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

## 概况

Django 1.5 中最重要的新功能是 [可配置的用户模型](#configurable-user-model)。在 Django 1.5 之前，希望使用 Django 的身份验证框架（[`django.contrib.auth`](/zh-hans/5.1/topics/auth/#module-django.contrib.auth)）的应用程序被强制使用 Django 对 "用户" 的定义。在 Django 1.5 中，现在可以将 `User` 模型替换为自己编写的模型。这可以是对现有 `User` 模型的简单扩展，例如，您可以添加 Twitter 或 Facebook ID 字段，或者您可以完全替换 `User`，使用完全为您的站点定制的模型。

Django 1.5 也是第一个支持 [Python 3](#python-3-support) 的版本！我们将此支持标记为 "实验性"，因为我们还不认为它已经可以用于生产环境，但已经为您提供了开始将您的应用程序移植到 Python 3 的一切必要条件。我们的下一个发布版，Django 1.6，将完全支持 Python 3，没有任何限制。

Django 1.5 中其他值得注意的新功能包括：

- [保存模型字段的子集支持](#support-for-saving-a-subset-of-model-s-fields) \- [`Model.save()`](/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save) 现在接受一个 `update_fields` 参数，允许您在调用 `save()` 时指定要写回数据库的字段。这对于高并发操作和性能优化非常有帮助。
- 通过新的 [`StreamingHttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.StreamingHttpResponse) 响应类，更好地支持 [流式响应](#explicit-streaming-responses)。
- [GeoDjango](#geodjango) 现在支持 PostGIS 2.0。
- ... 还有更多; [请参见下面](#what-s-new-in-django-1-5)。

我们尽量在符合 [API 稳定政策](/zh-hans/5.1/misc/api-stability/) 的情况下引入新功能。然而，与以前的版本一样，Django 1.5 也包含一些轻微的 [不兼容变更](#backwards-incompatible-1-5)；从以前版本的 Django 升级的用户应该仔细阅读该列表。

一个已经弃用的特性值得注意的是转向“新风格” [`url`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-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 版本。根据 [我们的支持政策](/zh-hans/5.1/internals/release-process/)，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 的所有可能用途。

由于某些功能依赖尚未移植到 Python 3 的第三方软件，因此 Django 的部分功能无法使用，包括：

- MySQL 数据库后端（依赖于 MySQLdb）
- [`ImageField`](/zh-hans/5.1/ref/models/fields/#django.db.models.ImageField) （依赖于 PIL）
- [`LiveServerTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.LiveServerTestCase) （依赖于 Selenium WebDriver）

此外，Django 不仅仅是一个 Web 框架；它还是一个可插拔组件的生态系统。目前，很少有第三方应用程序已移植到 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 模型的任何特定功能。

请查看 [自定义用户模型的文档](/zh-hans/5.1/topics/auth/customizing/#auth-custom-user) 以获取更多详细信息。

### 支持保存模型字段的子集

方法 [`Model.save()`](/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save) 现在有一个新的关键字参数 `update_fields`。通过使用这个参数，可以仅保存模型字段的选择列表。这在性能方面或在尝试避免覆盖并发更改时可能很有用。

被延迟加载的实例（通过 `.only()` 或 `.defer()` 加载的实例）将自动保存仅加载的字段。如果在加载后手动设置了任何字段，这些字段在保存时也将得到更新。

请查看 [`Model.save()`](/zh-hans/5.1/ref/models/instances/#django.db.models.Model.save) 的文档以获取更多详细信息。

### 缓存相关模型实例

在遍历关系时，ORM 将避免重新获取之前已加载的对象。例如，使用教程中的模型：

```pycon
>>> first_poll = Poll.objects.all()[0]
>>> first_choice = first_poll.choice_set.all()[0]
>>> first_choice.poll is first_poll
True
```

在 Django 1.5 中，第三行不再触发新的 SQL 查询来获取 `first_choice.poll`；它已经由第二行设置了。

对于一对一关系，双方都可以被缓存。对于多对一关系，只能缓存关系的单一一方。这在与 `prefetch_related` 结合使用时特别有帮助。

### 明确支持流式响应

在 Django 1.5 之前，可以通过将迭代器传递给 [`HttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponse) 来创建流式响应。但这是不可靠的：任何访问 [`content`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponse.content) 属性的中间件都会提前消耗迭代器。

现在，你可以使用新的 [`StreamingHttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.StreamingHttpResponse) 类明确生成流式响应。这个类公开了一个 [`streaming_content`](/zh-hans/5.1/ref/request-response/#django.http.StreamingHttpResponse.streaming_content) 属性，它是一个迭代器。

由于 [`StreamingHttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.StreamingHttpResponse) 没有 `content` 属性，需要访问响应内容的中间件必须检测流式响应并相应地处理。

### `{% verbatim %}` 模板标签

为了更轻松地处理与 Django 语法冲突的 JavaScript 模板，你现在可以使用 [`verbatim`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-verbatim) 块标签来避免解析标签的内容。

### 检索与代理模型相关联的 `ContentType` 实例

方法 [`ContentTypeManager.get_for_model()`](/zh-hans/5.1/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentTypeManager.get_for_model) 和 [`ContentTypeManager.get_for_models()`](/zh-hans/5.1/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentTypeManager.get_for_models) 现在有一个新的关键字参数，分别是 `for_concrete_model` 和 `for_concrete_models`。通过使用这个参数并传递 `False`，现在可以检索与代理模型相关联的 [`ContentType`](/zh-hans/5.1/ref/contrib/contenttypes/#django.contrib.contenttypes.models.ContentType)。

### 类基视图上下文中的新变量 `view`

在所有 [通用类基视图](/zh-hans/5.1/topics/class-based-views/) （或继承自 `ContextMixin` 的任何类基视图）中，上下文字典包含一个指向 `View` 实例的 `view` 变量。

### GeoDjango

- [`LineString`](/zh-hans/5.1/ref/contrib/gis/geos/#django.contrib.gis.geos.LineString) 和 [`MultiLineString`](/zh-hans/5.1/ref/contrib/gis/geos/#django.contrib.gis.geos.MultiLineString) GEOS 对象现在支持 [`interpolate()`](/zh-hans/5.1/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry.interpolate) 和 [`project()`](/zh-hans/5.1/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry.project) 方法（称为线性参考）。
- [`GEOSGeometry`](/zh-hans/5.1/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry) 对象的 `wkb` 和 `hex` 属性保留了 Z 维度。
- 已添加对 PostGIS 2.0 的支持，并且已放弃对 GDAL \< 1.5 的支持。

### 新教程

文档中的新内容包括全新的 [教程 3](/zh-hans/5.1/intro/tutorial03/) 和新的 [测试教程](/zh-hans/5.1/intro/tutorial05/)。一个新的部分，"高级教程"，提供了 [如何编写可重用应用程序](/zh-hans/5.1/intro/reusable-apps/) 以及新贡献者的逐步指南 [为 Django 编写你的第一个补丁](/zh-hans/5.1/intro/contributing/)。

### 次要特性

Django 1.5 还包括一些值得注意的较小改进：

- 模板引擎现在将 `True`、`False` 和 `None` 解释为相应的 Python 对象。
- [`django.utils.timezone`](/zh-hans/5.1/ref/utils/#module-django.utils.timezone) 提供了一个帮助程序，用于在不同时区之间转换带有时区信息的日期时间。请查看 [`localtime()`](/zh-hans/5.1/ref/utils/#django.utils.timezone.localtime)。
- 通用视图支持 OPTIONS 请求。
- 当通过 [`call_command()`](/zh-hans/5.1/ref/django-admin/#django.core.management.call_command) 从代码中调用管理命令时，管理命令不再引发 `SystemExit`。任何由命令引发的异常（主要是 [`CommandError`](/zh-hans/5.1/howto/custom-management-commands/#django.core.management.CommandError)）将被传播。

  此外，当在自定义命令中输出错误或消息时，现在应该使用 `self.stdout.write('message')` 和 `self.stderr.write('error')` （参见 [管理命令输出](/zh-hans/5.1/howto/custom-management-commands/#management-commands-output) 中的说明）。
- [`dumpdata`](/zh-hans/5.1/ref/django-admin/#django-admin-dumpdata) 管理命令现在逐行输出数据，以防止在导出大型数据集时出现内存不足错误。
- 在加拿大的本地化中，已经添加了 `pq` 作为魁北克省的可接受缩写。这是一个旧的缩写。
- [receiver](/zh-hans/5.1/topics/signals/#connecting-receiver-functions) 装饰器现在可以通过提供一个信号列表来连接多个信号。
- 在管理员界面中，您现在可以根据用户所属的群组来筛选用户。
- [`QuerySet.bulk_create()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create) 现在具有一个 batch\_size 参数。默认情况下，batch\_size 是无限的，除了 SQLite，其中单个批次受限，以确保不超过每个查询的 999 个参数。
- [`LOGIN_URL`](/zh-hans/5.1/ref/settings/#std-setting-LOGIN_URL) 和 [`LOGIN_REDIRECT_URL`](/zh-hans/5.1/ref/settings/#std-setting-LOGIN_REDIRECT_URL) 设置现在也接受视图函数名称和 [命名的 URL 模式](/zh-hans/5.1/topics/http/urls/#naming-url-patterns)。这允许您减少配置的重复。更多信息可以在 [`login_required()`](/zh-hans/5.1/topics/auth/default/#django.contrib.auth.decorators.login_required) 文档中找到。
- Django 现在提供了一个 mod\_wsgi [认证处理程序](/zh-hans/5.1/howto/deployment/wsgi/apache-auth/)。
- 在某些情况下，[`QuerySet.delete()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.delete) 和 [`Model.delete()`](/zh-hans/5.1/ref/models/instances/#django.db.models.Model.delete) 现在可以采用快速路径。快速路径可以减少查询和减少加载到内存中的对象。请查看 [`QuerySet.delete()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.delete) 以获取详细信息。
- 一个 `ResolverMatch` 的实例被存储在请求上，命名为 `resolver_match`。
- 默认情况下，当 [`DEBUG`](/zh-hans/5.1/ref/settings/#std-setting-DEBUG) 为 `True` 时，所有达到 `django` 日志器的日志消息都会发送到控制台（除非您在 [`LOGGING`](/zh-hans/5.1/ref/settings/#std-setting-LOGGING) 设置中重新定义了日志器）。
- 在使用 [`RequestContext`](/zh-hans/5.1/ref/templates/api/#django.template.RequestContext) 时，现在可以在模板中使用 `{% if 'someapp.someperm' in perms %}` 来查找权限。
- 不再需要在根模板目录中拥有 `404.html` 和 `500.html` 模板。当这些模板找不到时，Django 会输出一些基本的错误消息。仍然建议作为良好的实践提供这些模板，以便向用户呈现漂亮的错误页面。
- [`django.contrib.auth`](/zh-hans/5.1/topics/auth/#module-django.contrib.auth) 提供了一个新的信号，每当用户登录失败时都会发出该信号。请查看 [`user_login_failed`](/zh-hans/5.1/ref/contrib/auth/#django.contrib.auth.signals.user_login_failed)。
- 新的 [`loaddata --ignorenonexistent`](/zh-hans/5.1/ref/django-admin/#cmdoption-loaddata-ignorenonexistent) 选项会忽略不再存在的字段的数据。
- [`assertXMLEqual()`](/zh-hans/5.1/topics/testing/tools/#django.test.SimpleTestCase.assertXMLEqual) 和 [`assertXMLNotEqual()`](/zh-hans/5.1/topics/testing/tools/#django.test.SimpleTestCase.assertXMLNotEqual) 这两个新的断言允许您在语义级别测试 XML 内容的相等性，而不必关心语法差异（空格、属性顺序等）。
- 当同一浏览器会话中的 REMOTE\_USER 头消失时，RemoteUserMiddleware 现在会强制注销。
- 基于缓存的会话后端（[cache-based session backend](/zh-hans/5.1/topics/http/sessions/#cached-sessions-backend)）可以将会话数据存储在非默认的缓存中。
- 现在可以在模型上创建多列索引。阅读 `index_together` 文档以获取更多信息。
- 在 Django 的日志配置中，详细的弃用警告被启用，并且警告被捕获到日志系统中。已记录的警告通过 `console` 日志处理程序路由，其默认情况下需要 [`DEBUG`](/zh-hans/5.1/ref/settings/#std-setting-DEBUG) 为 True 才能生成输出。因此，在开发环境中，DeprecationWarnings 应该以与 Python 版本 \< 2.7 中相同的方式打印到控制台。
- [`django.contrib.admin.ModelAdmin.message_user()`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.message_user) 方法的 API 已经修改，以接受额外的参数，增加了类似于 [`django.contrib.messages.add_message()`](/zh-hans/5.1/ref/contrib/messages/#django.contrib.messages.add_message) 的功能。这对于从管理操作生成错误消息非常有用。
- 管理员的列表过滤器现在可以根据每个请求进行自定义，这要归功于新的 [`django.contrib.admin.ModelAdmin.get_list_filter()`](/zh-hans/5.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_list_filter) 方法。

## 1.5 中的向后不兼容更改

> **Warning**
>
> 除了本节中概述的更改外，确保查看 [弃用计划](/zh-hans/5.1/internals/deprecation/#deprecation-removed-in-1-5)，以了解已删除的任何功能。如果您没有在给定功能的弃用时间表内更新您的代码，其删除可能会被视为向后不兼容的更改。

### 在生产环境中必须设置 `ALLOWED_HOSTS`

新的 [`ALLOWED_HOSTS`](/zh-hans/5.1/ref/settings/#std-setting-ALLOWED_HOSTS) 设置验证请求的 `Host` 头并保护免受主机投毒攻击。此设置现在在 [`DEBUG`](/zh-hans/5.1/ref/settings/#std-setting-DEBUG) 为 `False` 时是必需的，否则 [`django.http.HttpRequest.get_host()`](/zh-hans/5.1/ref/request-response/#django.http.HttpRequest.get_host) 将引发 [`SuspiciousOperation`](/zh-hans/5.1/ref/exceptions/#django.core.exceptions.SuspiciousOperation)。更多详情请参阅新设置的 [`完整文档`](/zh-hans/5.1/ref/settings/#std-setting-ALLOWED_HOSTS)。

### 抽象模型上的管理器

抽象模型可以定义一个自定义管理器，并且该管理器 [将被任何扩展抽象模型的具体模型继承](/zh-hans/5.1/topics/db/managers/#custom-managers-and-inheritance)。然而，如果您尝试在抽象模型上调用管理器的方法，现在将会引发异常。以前，允许调用，但只要尝试进行任何数据库操作，通常会导致数据库报错 "表不存在"。

如果您在管理器上有功能，一直在使用抽象类进行调用，您应该将该逻辑迁移到抽象类上的 Python `staticmethod` 或 `classmethod`。

### 基于类的年度归档视图中的上下文

为了与其他基于日期的通用视图保持一致，[`YearArchiveView`](/zh-hans/5.1/ref/class-based-views/generic-date-based/#django.views.generic.dates.YearArchiveView) 现在将 `year` 作为一个 [`datetime.date`](https://docs.python.org/3/library/datetime.html#datetime.date) 而不是一个字符串传递给上下文。如果您在模板中使用了 `{{ year }}`，您必须将其替换为 `{{ year|date:"Y" }}`。

`next_year` 和 `previous_year` 也被添加到上下文中。它们根据 `allow_empty` 和 `allow_future` 进行计算。

### 基于类的年度和月度归档视图中的上下文

[`YearArchiveView`](/zh-hans/5.1/ref/class-based-views/generic-date-based/#django.views.generic.dates.YearArchiveView) 和 [`MonthArchiveView`](/zh-hans/5.1/ref/class-based-views/generic-date-based/#django.views.generic.dates.MonthArchiveView) 的文档中曾经说明在上下文中提供一个按升序排序的 `date_list`，就像它们的基于函数的前身一样，但实际上它是按降序排序的。在1.5版本中，文档中的顺序已经恢复。在模板中迭代 `date_list` 时，您可能需要添加（或删除） `reversed` 关键字：

```html+django
{% for date in date_list reversed %}
```

[`ArchiveIndexView`](/zh-hans/5.1/ref/class-based-views/generic-date-based/#django.views.generic.dates.ArchiveIndexView) 仍然以降序提供一个 `date_list`。

### TemplateView 中的上下文

为了与其他通用视图的设计保持一致，[`TemplateView`](/zh-hans/5.1/ref/class-based-views/base/#django.views.generic.base.TemplateView) 不再将一个 `params` 字典传递到上下文中，而是直接将来自 URLconf 的变量传递到上下文中。

### HTTP 请求中的非表单数据

[`request.POST`](/zh-hans/5.1/ref/request-response/#django.http.HttpRequest.POST) 将不再包含通过非表单特定内容类型的 HTTP 请求发布的数据。在以前的版本中，使用除 `multipart/form-data` 或 `application/x-www-form-urlencoded` 之外的内容类型发布的数据仍然会在 [`request.POST`](/zh-hans/5.1/ref/request-response/#django.http.HttpRequest.POST) 属性中表示出来。希望访问这些情况下的原始 POST 数据的开发人员应该使用 [`request.body`](/zh-hans/5.1/ref/request-response/#django.http.HttpRequest.body) 属性。

### [`request_finished`](/zh-hans/5.1/ref/signals/#django.core.signals.request_finished) 信号

Django 曾经在视图函数返回响应后立即发送 [`request_finished`](/zh-hans/5.1/ref/signals/#django.core.signals.request_finished) 信号。这与延迟内容生成的 [流式响应](/zh-hans/5.1/ref/request-response/#httpresponse-streaming) 产生了不良互动。

现在，该信号在内容被 WSGI 网关完全消耗后发送。如果您依赖于在将响应内容发送给客户端之前触发信号，这可能会导致不兼容。如果是这样，您应该考虑使用 [中间件](/zh-hans/5.1/topics/http/middleware/)。

> **Note**
>
> 一些 WSGI 服务器和中间件在处理请求后并不总是调用响应对象的 `close` 方法，特别是在 1.2.6 之前的 uWSGI 和 Sentry 的错误报告中间件在 2.0.7 之前的版本中存在这个问题。在这些情况下，`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`](https://docs.python.org/3/library/json.html#module-json) 模块。理论上，这个更改是无害的。不幸的是，由于不同版本的 `simplejson` 之间的不兼容性，它可能在某些情况下触发错误。

Django 1.4 中与 JSON 相关的功能始终使用了 `django.utils.simplejson`。这个模块实际上是：

- 如果有一个系统版本的 `simplejson`，如果有的话（即 `import simplejson` 能正常工作），如果它比 Django 内置的版本更新，或者它具有 C 加速，或者
- 标准库中的 [`json`](https://docs.python.org/3/library/json.html#module-json) 模块，如果可用（即 Python 2.6 或更高版本），或者
- 一个内置版本的 `simplejson`，版本号为 2.0.7。

在 Django 1.5 中，这些功能使用了 Python 的 [`json`](https://docs.python.org/3/library/json.html#module-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 #18023](https://code.djangoproject.com/ticket/18023#comment:10) 中找到。

总的来说，如果你安装了 `simplejson` 并且你的代码直接使用了 Django 的序列化内部，例如 `django.core.serializers.json.DjangoJSONEncoder`，从 `simplejson` 切换到 [`json`](https://docs.python.org/3/library/json.html#module-json) 可能会破坏你的代码。（一般情况下，对内部的更改不会被记录在文档中；我们在这里做了一个例外。）

目前，Django 的维护者认为使用标准库中的 [`json`](https://docs.python.org/3/library/json.html#module-json) 提供了最强的向后兼容性保证。他们建议从现在开始使用它。

### 哈希方法参数的字符串类型

如果你编写了一个自定义的密码哈希器（[自定义密码哈希器](/zh-hans/5.1/topics/auth/passwords/#auth-password-storage)），你的 `encode()`、`verify()` 或 `safe_summary()` 方法应该接受 Unicode 参数（`password`、`salt` 或 `encoded`）。如果哈希方法中需要字节串，你可以使用 [`force_bytes()`](/zh-hans/5.1/ref/utils/#django.utils.encoding.force_bytes) 实用程序来编码字符串。

### 验证 previous\_page\_number 和 next\_page\_number

在使用 [对象分页](/zh-hans/5.1/topics/pagination/) 时，[`Page`](/zh-hans/5.1/ref/paginator/#django.core.paginator.Page) 对象的 `previous_page_number()` 和 `next_page_number()` 方法现在会检查返回的页码是否在现有的页面范围内。如果页码过低或过高，它们将引发 [`InvalidPage`](/zh-hans/5.1/ref/paginator/#django.core.paginator.InvalidPage) 异常。

### PostgreSQL 中 autocommit 数据库选项的行为已更改

PostgreSQL 的自动提交选项在以前的广告中没有按照预期工作。对于单个事务块确实有效，但是在第一个块结束后，自动提交行为没有被恢复。这个错误在 1.5 版本中已经修复。虽然这只是一个错误修复，但如果你正在使用 PostgreSQL 与自动提交选项，值得检查你的应用程序的行为。

### 500 响应时会话未保存。

如果响应的状态码是 500，Django 的会话中间件将跳过保存会话数据。

### 管理员登录失败时进行电子邮件检查。

在 Django 1.5 之前，如果您尝试登录到管理员界面并错误地使用电子邮件地址而不是用户名，管理员界面会提供警告，建议您的电子邮件地址不是用户名。在 Django 1.5 中，引入了 [自定义用户模型](/zh-hans/5.1/topics/auth/customizing/#auth-custom-user)，需要删除此警告。这不会改变管理员站点的登录行为；它只影响在一种特定的登录失败模式下显示的警告消息。

### 测试执行的变化

一些关于测试执行的变化已经引入，这可能对某些测试设置不兼容。

#### 在 `django.test.TransactionTestCase` 中进行数据库刷新操作

在 [`TransactionTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase) 中，在每次测试运行之前对测试数据库进行截断操作。

为了能够以任何顺序运行单元测试，并确保它们始终相互隔离，[`TransactionTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase) 现在会在每次测试运行之后重置数据库。

#### 不再隐式重置数据库序列

[`TransactionTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase) 测试过去会自动重置主键序列，以及上述描述的数据库刷新操作。

这已经改变，所以不会隐式重置任何序列。这可能导致依赖于硬编码主键值的 [`TransactionTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase) 测试出现问题。

新的 [`reset_sequences`](/zh-hans/5.1/topics/testing/advanced/#django.test.TransactionTestCase.reset_sequences) 属性可以用于强制对可能需要的 [`TransactionTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase) 使用旧的行为。

#### 测试的顺序

为了确保所有的 `TestCase` 代码都从一个干净的数据库开始运行，测试现在按照以下顺序执行：

- 首先，运行所有单元测试（包括 [`unittest.TestCase`](https://docs.python.org/3/library/unittest.html#unittest.TestCase)、[`SimpleTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.SimpleTestCase)、[`TestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TestCase) 和 [`TransactionTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase)），它们之间没有特定的顺序保证或强制执行。
- 然后运行可能会更改数据库而不将其还原为原始状态的任何其他测试（例如 doctests）。

这不应该导致任何问题，除非你有一些现有的 doctests 假设之前执行过一个 [`TransactionTestCase`](/zh-hans/5.1/topics/testing/tools/#django.test.TransactionTestCase) 留下了一些数据库状态，或者单元测试依赖于在其他测试执行后保留某种状态。这样的测试已经非常脆弱，现在必须进行更改以能够独立运行。

### 为无效表单保留的 `cleaned_data` 字典

现在，经过表单验证后，总是存在 [`cleaned_data`](/zh-hans/5.1/ref/forms/api/#django.forms.Form.cleaned_data) 字典。当表单未通过验证时，它仅包含通过验证的字段。您应该使用 [`is_valid()`](/zh-hans/5.1/ref/forms/api/#django.forms.Form.is_valid) 方法来测试验证的成功与否，而不是通过表单上的 [`cleaned_data`](/zh-hans/5.1/ref/forms/api/#django.forms.Form.cleaned_data) 属性的存在或缺失来判断。

### 关于多个数据库的 `syncdb` 的行为

现在，`syncdb` 会查询数据库路由器，以确定在目标数据库中是否应创建内容类型（当启用 [`contenttypes`](/zh-hans/5.1/ref/contrib/contenttypes/#module-django.contrib.contenttypes) 时）和权限（当启用 [`auth`](/zh-hans/5.1/topics/auth/#module-django.contrib.auth) 时）。以前，即使使用 `--database` 选项指定了另一个数据库，它也会在默认数据库中创建它们。

如果您在多个数据库上使用 `syncdb`，应确保您的路由器只允许将内容类型和权限同步到其中一个数据库。有关更多信息，请参阅 [多数据库中的 contrib 应用程序行为](/zh-hans/5.1/topics/db/multi-db/#contrib-app-multiple-databases) 的文档。

### XML 反序列化器不会解析带有 DTD 的文档。

为了防止与外部实体引用和实体扩展相关的拒绝服务攻击，XML 模型反序列化器现在拒绝解析包含 DTD（DOCTYPE 定义）的 XML 文档。由于 XML 序列化器不输出 DTD，这只会影响传递给 Django 模型反序列化器的自定义创建的 XML 文档，而不会影响典型的用法。

### Formsets 的默认 `max_num` 值

表单集工厂的 `max_num` 参数的默认值为 `None` 不再默认允许表单集中的任意数量的表单。相反，为了防止内存耗尽攻击，它现在默认为限制为 1000 个表单。可以通过显式设置更高的 `max_num` 值来提高此限制。

### 杂项

- [`django.forms.ModelMultipleChoiceField`](/zh-hans/5.1/ref/forms/fields/#django.forms.ModelMultipleChoiceField) 现在将空的 `QuerySet` 作为空值返回，而不是空列表。
- [`int_to_base36()`](/zh-hans/5.1/ref/utils/#django.utils.http.int_to_base36) 对于非整数输入现在会正确引发 [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError)，而不是 [`ValueError`](https://docs.python.org/3/library/exceptions.html#ValueError)。
- 模板过滤器中的 `slugify` 现在作为标准的 Python 函数在 [`django.utils.text.slugify()`](/zh-hans/5.1/ref/utils/#django.utils.text.slugify) 中可用。同样，`remove_tags` 在 `django.utils.html.remove_tags()` 中也可用。
- 上传的文件不再默认创建为可执行文件。如果需要它们成为可执行文件，请更改 [`FILE_UPLOAD_PERMISSIONS`](/zh-hans/5.1/ref/settings/#std-setting-FILE_UPLOAD_PERMISSIONS) 以满足您的需求。新的默认值是 `0o666` （八进制），并且当前的掩码值首先被掩码掉。
- [`F 表达式`](/zh-hans/5.1/ref/models/expressions/#django.db.models.F) 支持位运算符 `&` 和 `|`。现在，可以使用 `.bitand()` 和 `.bitor()` 来代替这些运算符。移除 `&` 和 `|` 是为了与 [Q() 表达式](/zh-hans/5.1/topics/db/queries/#complex-lookups-with-q) 和 `QuerySet` 结合使用时保持一致，其中这些运算符被用作布尔 AND 和 OR 运算符。
- 在 `filter()` 调用中，当 [`F 表达式`](/zh-hans/5.1/ref/models/expressions/#django.db.models.F) 包含跨多值关联的查找时，它们并不总是重用与同一链中其他查找相同的关联。这已经发生了变化，现在 F() 表达式将始终与同一 `filter()` 调用中的其他查找使用相同的关联。
- [`csrf_token`](/zh-hans/5.1/ref/templates/builtins/#std-templatetag-csrf_token) 模板标签不再包含在一个 div 中。如果您需要针对 HTML5 之前的 Strict DTD 进行 HTML 验证，您应该在页面中添加一个 div。
- 已删除模板标签库 `adminmedia`，它只包含了已弃用的模板标签 `{% admin_media_prefix %}`。尝试使用 `{% load adminmedia %}` 加载它将会失败。如果您的模板仍然包含该行代码，您必须将其删除。
- 由于一个实现上的疏忽，以前可以在没有启用 [django.contrib.sites](/zh-hans/5.1/ref/contrib/sites/) 的情况下使用 [django.contrib.redirects](/zh-hans/5.1/ref/contrib/redirects/)。现在不再允许这样做了。如果您正在使用 `django.contrib.redirects`，请确保 [`INSTALLED_APPS`](/zh-hans/5.1/ref/settings/#std-setting-INSTALLED_APPS) 包含 `django.contrib.sites`。
- [`BoundField.label_tag`](/zh-hans/5.1/ref/forms/api/#django.forms.BoundField.label_tag) 现在会对其 `contents` 参数进行 HTML 转义。要避免 HTML 转义，可以在传递参数之前使用 [`django.utils.safestring.mark_safe()`](/zh-hans/5.1/ref/utils/#django.utils.safestring.mark_safe)。
- 通过 [`select_related()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related) 获取的反向一对一关系现在会引发 [`DoesNotExist`](/zh-hans/5.1/ref/models/class/#django.db.models.Model.DoesNotExist) 异常，而不是返回 `None`。

## 在 1.5 中被废弃的功能

### `django.contrib.localflavor`

localflavor 贡献应用程序已分成单独的包。`django.contrib.localflavor` 本身将在 Django 1.6 中移除，经过加速的弃用期。

新的软件包已在 GitHub 上提供。核心团队无法长期高效地维护这些软件包 - 目前仅覆盖了几个国家；与翻译类似，维护工作将移交给感兴趣的社区成员。

### `django.contrib.markup`

markup contrib 模块已被弃用，并将按照加速弃用计划进行处理。直接使用 Python 标记库或第三方标签库比 Django 在框架中维护此功能更受推荐。

### `AUTH_PROFILE_MODULE`

引入 [自定义用户模型](/zh-hans/5.1/topics/auth/customizing/#auth-custom-user) 后，不再需要内置机制来存储用户配置文件数据。

您仍然可以定义与用户模型具有一对一关系的用户配置文件模型 - 实际上，对于许多需要将数据与用户帐户关联的应用程序，这将是一个适当的设计模式。然而，不再应使用 `AUTH_PROFILE_MODULE` 设置以及用于访问用户配置文件模型的 `django.contrib.auth.models.User.get_profile()` 方法。

### [`HttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponse) 的流式传输行为

Django 1.5 不再支持通过将迭代器传递给 [`HttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponse) 来流式传输响应的能力。如果您依赖此行为，请切换到 [`StreamingHttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.StreamingHttpResponse)。请参阅 [明确支持流式响应](#explicit-streaming-responses)。

在 Django 1.7 及以上版本中，迭代器将立即被 [`HttpResponse`](/zh-hans/5.1/ref/request-response/#django.http.HttpResponse) 消耗。

### `django.utils.simplejson`

由于 Django 1.5 不再支持 Python 2.5，我们现在可以依赖于 Python 标准库中的 [`json`](https://docs.python.org/3/library/json.html#module-json) 模块，因此我们已经移除了我们自己的 `simplejson` 副本。您现在应该导入 [`json`](https://docs.python.org/3/library/json.html#module-json)，而不是 `django.utils.simplejson`。

不幸的是，这个改变可能会产生意想不到的副作用，因为不同版本的 `simplejson` 之间存在不兼容性，详见 [不兼容变更](#simplejson-incompatibilities) 部分。如果您依赖于在它成为 Python 的 [`json`](https://docs.python.org/3/library/json.html#module-json) 之后添加到 `simplejson` 的功能，您应该显式导入 `simplejson`。

### `django.utils.encoding.StrAndUnicode`

`django.utils.encoding.StrAndUnicode` 混合类已被弃用。应该定义一个 `__str__` 方法，并应用 `django.utils.encoding.python_2_unicode_compatible` 装饰器。

### `django.utils.itercompat.product`

`django.utils.itercompat.product` 函数已被弃用。应该使用内置的 [`itertools.product()`](https://docs.python.org/3/library/itertools.html#itertools.product)。

### `cleanup` 管理命令

`cleanup` 管理命令已被弃用，并被 [`clearsessions`](/zh-hans/5.1/ref/django-admin/#django-admin-clearsessions) 取代。

### `daily_cleanup.py` 脚本

未记录的 `daily_cleanup.py` 脚本已被弃用。请使用 [`clearsessions`](/zh-hans/5.1/ref/django-admin/#django-admin-clearsessions) 管理命令。

### `select_related` 中的 `depth` 关键字参数

在 [`select_related()`](/zh-hans/5.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related) 中的 `depth` 关键字参数已被弃用。您应该使用字段名称代替。
