# Django 5.2.8 documentation

# Django 1.2 版本发行说明

2017 年 5 月 17 日

欢迎来到 Django 1.2 版本！

经过近一年的努力，Django 1.2 收录了令人印象深刻的一系列 新特性 和大量的错误修复。这些发布说明涵盖了新特性，以及在从 Django 1.1 或更早版本升级时需要注意的重要更改。

## 概况

Django 1.2 引入了几个重要的大型新功能，包括：

- 在单个 Django 实例中支持 多个数据库连接。

- 模型验证 受到了 Django 的表单验证的启发。

- 极大地 改进了跨站点请求伪造 (CSRF) 的保护机制。

- 一个新的支持匿名和已验证用户的 cookie 和会话消息的 用户“消息”框架。

- 对象级权限、匿名用户的权限 和 更灵活的用户名要求 的挂钩。

- 通过 电子邮件后端 自定义电子邮件发送。

- 新的 "智能" if 模板标签 支持比较运算符。

这仅仅是亮点；完整的细节和功能列表 可能在下面找到。

See also

Django Advent 用一系列的文章和教程详细介绍了 Django 1.2 版本的发布以及其中一些新功能。

尽可能地，这些功能都是按照 我们的 API 稳定性政策 来引入的，以保持向后兼容性。

然而，有一些功能以某种方式发生了变化，对某些用户来说将不向后兼容。主要的变化包括：

- 已取消对 Python 2.3 的支持。请参阅下面的详细说明。

- 新的 CSRF 保护框架与旧系统不向后兼容。在 Django 1.4 中移除旧系统之前，旧系统的用户不会受到影响。

  然而，升级到新的 CSRF 保护框架需要进行一些重要的不向后兼容的更改，详细信息请参见下面的 CSRF 保护。

- 自定义 `Field` 子类的作者应该注意，一些方法的原型发生了变化，详细信息请参见下面的 Field 上的 get_db_prep_*() 方法。

- 模板标签的内部发生了一些变化；需要存储状态的自定义模板标签的作者（例如，自定义控制流标签）应确保他们的代码遵循了新的 有状态模板标签 的规则。

- 来自 `django.contrib.auth` 的 `user_passes_test()`、`login_required()` 和 `permission_required()` 装饰器仅适用于函数，不再适用于方法。有一个简单的一行修复方法，详细信息请参见下面的 详细说明。

再次强调，这些只是会影响大多数用户的主要功能。从以前版本的 Django 升级的用户强烈建议查看完整的 不向后兼容的更改列表 和 不建议使用的功能列表。

## Python 兼容性

虽然这不是一个新功能，但值得注意的是，自 Django 首次公开亮相以来，Django 1.2 首次改变了我们的 Python 兼容性政策。以前的 Django 版本已经过测试并支持从 2.3 开始的 2.x Python 版本；然而，Django 1.2 放弃了对 Python 2.3 的官方支持。因此，现在 Django 所需的最低 Python 版本为 2.4，Django 已经过测试并支持 Python 2.4 、 2.5 和 2.6，并将支持尚未发布的 Python 2.7 。

这个变化应该只会影响少数 Django 用户，因为大多数操作系统供应商现在都默认安装 Python 2.4 或更新的版本。然而，如果你仍然在使用 Python 2.3，那么你需要继续使用 Django 1.1，直到你可以升级为止；根据 我们的支持政策，Django 1.1 将在 Django 1.3 发布之前继续获得安全支持。

Django 针对整体 2.x Python 支持的发展路线图以及最终过渡到 Python 3.x 的计划目前正在制定中，并将在 Django 1.3 发布之前宣布。

## Django 1.2 新特性

### 支持多数据库

Django 1.2 增加了在你的 Django 项目中使用 多个数据库 的能力。可以使用 `QuerySet` 对象上的 `using()` 方法在特定数据库上发出查询。在调用 `save()` 时，可以通过提供 `using` 参数将单个对象保存到特定的数据库。

### 模型验证

模型实例现在支持 验证自己的数据，而且模型字段和表单字段现在都接受可配置的 验证器列表，指定了可重用的封装的验证行为。但是，请注意，验证仍然必须显式地执行。只是调用模型实例的 `save()` 方法不会对实例的数据执行任何验证。

### 改进的 CSRF 保护

Django 现在在防范 跨站请求伪造（CSRF）攻击 方面有了更加完善的保护。这种类型的攻击发生在恶意网站包含一个链接、一个表单按钮或一些 JavaScript，旨在使用已登录用户的凭据在其浏览器中访问恶意网站的用户来执行某些操作。相关的一种攻击类型是“登录 CSRF”，其中攻击站点欺骗用户的浏览器，使其使用别人的凭据登录到某个站点，这也得到了覆盖。

### 消息框架

Django 现在包括一个强大且可配置的 消息框架，内置支持基于 cookie 和会话的消息传递，适用于匿名和已验证的客户端。消息框架替代了不建议使用的用户消息 API，并允许你在一个请求中临时存储消息，然后在后续请求中检索它们以显示（通常是下一个请求）。

### 对象级权限

已添加了在每个对象级别指定权限的基础。尽管核心中没有此功能的实现，但自定义身份验证后端可以提供此实现，并将被 `django.contrib.auth.models.User` 使用。有关更多信息，请参阅 身份验证文档。

### 匿名用户的权限

If you provide a custom auth backend with `supports_anonymous_user` set to `True`, AnonymousUser will check the backend for permissions, just like User already did. This is useful for centralizing permission handling - apps can always delegate the question of whether something is allowed or not to the authorization/authentication backend. See the authentication docs for more details.

### 放宽用户名要求

内置的 `User` 模型的 `username` 字段现在允许更广泛范围的字符，包括 `@`、`+`、`.` 和 `-` 字符。

### 邮件后端

现在你可以 配置 Django 发送电子邮件的方式。不再使用 SMTP 来发送所有电子邮件，你现在可以选择一个可配置的电子邮件后端来发送消息。如果你的托管提供商使用沙盒或其他非-SMTP 发送邮件的技术，你现在可以构建一个电子邮件后端，使 Django 的标准 邮件发送方法 可以使用这些设施。

这也使得调试邮件发送更加容易。Django 提供了后端实现，允许你将电子邮件发送到 文件、控制台，或 内存。你甚至可以配置所有的电子邮件都被 丢弃。

### "智能" `if` 标签

`if` 标签已升级为更加强大。首先，我们增加了对比较运算符的支持。你不再需要输入如下内容：

    {% ifnotequal a b %}
     ...
    {% endifnotequal %}

现在你可以这样做：

    {% if a != b %}
     ...
    {% endif %}

除非你是怀旧型的，否则没有理由再使用 `{% ifequal %}` 或 `{% ifnotequal %}`。

支持的运算符包括 `==`、`!=`、`<`、`>`、`<=`、`>=`、`in` 和 `not in`，它们都像 Python 运算符一样工作，此外还支持 `and`、`or` 和 `not`，这些已经被支持了。

此外，现在可以在 `if` 表达式中使用过滤器。例如：

    <div
      {% if user.email|lower == message.recipient|lower %}
        class="highlight"
      {% endif %}
    >{{ message }}</div>

### 模板缓存

在之前的 Django 版本中，每次渲染模板时都会重新从磁盘加载。在 Django 1.2 中，你可以使用 缓存模板加载器 来加载模板一次，然后为每个后续的渲染缓存结果。如果你的模板被拆分成许多较小的子模板（使用 `{% extends %}` 或 `{% include %}` 标签），这可以导致显著的性能提升。

作为一个副作用，现在更容易支持非 Django 模板语言。

### 基于类的模板加载器

作为引入 模板缓存 所做的更改的一部分，并遵循 Django 中的一般趋势，模板加载器 API 已经被修改为使用封装在 Python 类中的模板加载机制，而不是像 Django 1.1 中只有函数可用。

所有 随 Django 一起提供的模板加载器 都已经转换到新的 API，但它们仍然实现了基于函数的 API，而模板核心机制仍然接受基于函数的加载器（内置或第三方的），因此在现有项目中不需要立即修改你的 `TEMPLATE_LOADERS` 设置，如果你不更改它，事情将一直正常工作，直到 Django 1.3 版本为止。

If you have developed your own custom template loaders we suggest to consider porting them to a class-based implementation because the code for backwards compatibility with function-based loaders starts its deprecation process in Django 1.2 and will be removed in Django 1.4. There is a description of the API these loader classes must implement in the template API reference and you can also examine the source code of the loaders shipped with Django.

### 固定装置中的自然键

现在，可以使用 自然键 来引用远程对象的固定数据。这种查找方案是一种替代传统基于主键的对象引用的方式，可以提高可读性，并解决引用那些主键值可能不可预测或未知的对象的问题。

### 测试的快速失败

`django-admin.py` 的 `test` 子命令和用于运行 Django 自己的测试套件的 `runtests.py` 脚本现在都支持 `--failfast` 选项。当指定此选项时，测试运行器在遇到失败后会退出，而不是继续运行测试。此外，在测试运行期间改进了对 `Ctrl-C` 的处理，触发了从测试运行中优雅退出，并报告中断前运行的测试的详细信息。

### `BigIntegerField`

现在，模型可以使用 64 位的 `BigIntegerField` 类型。

### 改善的本地化

Django 的 国际化框架 已经扩展了，具备了区域感知的格式化和表单处理功能。这意味着，如果启用了国际化，模板中的日期和数字将使用当前区域设置指定的格式进行显示。Django 还会在解析表单中的数据时使用本地化格式。有关更多详细信息，请参阅 本地格式化。

### `ModelAdmin` 中的 `readonly_fields`

`django.contrib.admin.ModelAdmin.readonly_fields` 已经被添加，用于在模型和内联的添加/更改页面上启用不可编辑的字段。字段和计算值可以显示在可编辑字段旁边。

### 可定制的语法高亮

现在，你可以使用 `DJANGO_COLORS` 环境变量来修改或禁用 `django-admin.py` 用于提供 语法高亮 的颜色。

### 将聚合订阅作为视图

Syndication feeds 现在可以直接用作你的 URLconf 中的视图。这意味着你可以完全控制你的 feeds 的 URL 结构。与任何其他视图一样，feeds 视图会传递一个 `request` 对象，因此你可以像处理常规视图一样进行操作，如基于用户的访问控制，或将 feed 作为具名 URL。

### GeoDjango

The most significant new feature for GeoDjango in 1.2 is support for multiple spatial databases. As a result, the following spatial database backends are now included:

- `django.contrib.gis.db.backends.postgis`

- `django.contrib.gis.db.backends.mysql`

- `django.contrib.gis.db.backends.oracle`

- `django.contrib.gis.db.backends.spatialite`

GeoDjango 现在支持 PostGIS 1.5 发布中添加的丰富功能。新功能包括对 geography 类型 的支持，并在地理坐标系统上启用了对非点几何图形的 距离查询。

已添加对 3D 几何字段的支持，可以通过在 `GeometryField` 中设置 `dim` 关键字为 3 来启用。作为此功能的一部分，还添加了 `Extent3D` 聚合和 `extent3d()` `GeoQuerySet` 方法。

新添加了 `force_rhr()`、`reverse_geom()` 和 `geohash()` `GeoQuerySet` 方法。

当平台支持时，更新了 GEOS 接口以使用线程安全的 C 库函数。

GDAL 接口现在允许用户在迭代 `Layer` 时设置 `spatial_filter`，以过滤返回的要素。

最后，GeoDjango 的文档 现在已经与 Django 的文档一起包括在内，不再单独托管在 `geodjango.org` 上。

### 在管理中使用 JavaScript 辅助处理内联相关对象。

如果用户的浏览器启用了 JavaScript，则管理中内联对象的界面现在允许动态添加和删除内联对象。没有启用 JavaScript 的浏览器的用户将不会看到内联对象行为的任何变化。

### 新的 `now` 模板标签格式说明符字符：`c` 和 `u`

`now` 的参数新增了两个新的格式字符：`c` 用于指定将日期时间值格式化为 ISO 8601 格式，`u` 允许输出日期时间或时间值的微秒部分。

这些新格式字符也在其他地方可用，如 `date` 和 `time` 模板过滤器、`humanize` 模板标签库以及新的 格式本地化 框架。

## 1.2 版本中的不向后兼容的更改。

在可能的情况下，上述新功能均以向后兼容的方式引入，遵循 我们的 API 稳定性政策。这意味着几乎所有与 Django 1.1 兼容的现有代码都将继续适用于 Django 1.2 版本；然而，这样的代码将开始发出警告（详情见下文）。

然而，有一些功能确实以一种对某些用户来说立即不向后兼容的方式发生了变化。这些变化将在下面详细说明。

### CSRF 保护。

我们对 CSRF 保护的工作方式进行了重大改变，详细信息请参阅 CSRF 文档。以下是你应该注意的主要变化：

- `CsrfResponseMiddleware` 和 `CsrfMiddleware` 已被弃用，并将在 Django 1.4 中完全删除，取而代之的是应该插入到表单中的模板标签。

- 所有的 contrib 应用都使用了一个 `csrf_protect` 装饰器来保护视图。这需要在模板中使用 `csrf_token` 模板标签。如果你已经使用了自定义模板来定制 contrib 视图，你必须阅读升级说明来修复这些模板。

  已删除文档

  当前 Django 文档中已删除了升级说明。请参考 Django 1.3 或更早版本的文档以查找这些说明。

- `CsrfViewMiddleware` 默认包含在 `MIDDLEWARE_CLASSES` 中。这默认启用了 CSRF 保护，因此接受 POST 请求的视图需要编写以与中间件一起使用。如何做到这一点的说明可以在 CSRF 文档中找到。

- 所有的 CSRF 已经从 contrib 转移到了核心（在旧的位置有向后兼容的导入，这些导入已被弃用，并将在 Django 1.4 中停止支持）。

### `Field` 上的 `get_db_prep_*()` 方法

在 Django 1.2 之前，自定义的 `Field` 可以定义多个函数，用于将 Python 值转换为与数据库兼容的值。一个自定义字段可能如下所示：

    class CustomModelField(models.Field):
        ...

        def db_type(self): ...

        def get_db_prep_save(self, value): ...

        def get_db_prep_value(self, value): ...

        def get_db_prep_lookup(self, lookup_type, value): ...

在 1.2 版本中，这三种方法的原型发生了变化，还引入了两种额外的方法：

    class CustomModelField(models.Field):
        ...

        def db_type(self, connection): ...

        def get_prep_value(self, value): ...

        def get_prep_lookup(self, lookup_type, value): ...

        def get_db_prep_save(self, value, connection): ...

        def get_db_prep_value(self, value, connection, prepared=False): ...

        def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False): ...

这些更改是为了支持多个数据库 - `db_type` 和 `get_db_prep_*` 不能再对其准备的数据库做任何假设。现在，`connection` 参数为准备方法提供了特定的连接，用于准备该值。

这两个新方法的存在是为了区分通用的数据准备需求和特定于数据库的需求。`prepared` 参数用于指示数据库准备方法是否已执行通用值准备。如果将未准备好的值（即 `prepared=False`）提供给 `get_db_prep_*()` 调用，它们应该调用相应的 `get_prep_*()` 调用来执行通用数据准备。

我们提供了转换函数，可以将符合旧原型的函数透明地转换为与新原型兼容的函数。但是，这些转换函数将在 Django 1.4 中移除，因此你应该尽快升级你的 `Field` 定义，以使用新的原型。

如果你的 `get_db_prep_*()` 方法没有使用数据库连接，你应该可以通过将 `get_db_prep_value()` 重命名为 `get_prep_value()`，将 `get_db_prep_lookup()` 重命名为 `get_prep_lookup()` 来进行升级。如果你需要数据库特定的转换，那么你需要提供一个实现 `get_db_prep_*` 的方法，使用 `connection` 参数来解析数据库特定的值。

### 有状态的模板标签

将渲染状态存储在其 `Node` 子类上的模板标签一直容易受到线程安全和其他问题的影响；然而，从Django 1.2开始，当与新的 cached template loader 一起使用时，它们可能也会引发问题。

所有内置的 Django 模板标签都可以安全地与缓存加载器一起使用，但如果你使用的是来自第三方包或你自己的代码的自定义模板标签，你应该确保每个标签的 `Node` 实现是线程安全的。更多信息，请参阅 模板标签线程安全注意事项。

如果你依赖于 Django 模板标签的实现 不 是线程安全的，你可能还需要更新你的模板。在这种情况下，`cycle` 标签最有可能受到影响，特别是当与 `include` 标签一起使用时。考虑以下模板片段：

    {% for object in object_list %}
        {% include "subtemplate.html" %}
    {% endfor %}

带有一个 `subtemplate.html`，其内容如下：

    {% cycle 'even' 'odd' %}

使用非线程安全的、 Django 1.2 之前的渲染器，输出如下：

    even odd even odd ...

使用线程安全的 Django 1.2 渲染器，你将得到：

    even even even even ...

这是因为每次渲染 `include` 标签都是独立的渲染。当 `cycle` 标签不是线程安全时，`cycle` 标签的状态会在同一个 `include` 的多次渲染之间泄漏。现在 `cycle` 标签是线程安全的，这种泄漏不再发生。

### `user_passes_test`, `login_required` 和 `permission_required`

`django.contrib.auth.decorators` 提供了装饰器 `login_required`、`permission_required` 和 `user_passes_test`。以前可以在函数上使用这些装饰器（其中第一个参数是 'request'），也可以在方法上使用（其中第一个参数是 'self'，第二个参数是 'request'）。不幸的是，发现了支持这种用法的代码存在缺陷：它只在有限的情况下工作，并且在不起作用时会产生非常难以调试的错误。

因此，已经移除了'auto adapt'行为，如果你在方法上使用这些装饰器，你需要手动应用 `django.utils.decorators.method_decorator()` 来将装饰器转换为适用于方法的装饰器。例如，你需要将代码从这样改为：

    class MyClass(object):
        @login_required
        def my_view(self, request):
            pass

改成这个：

    from django.utils.decorators import method_decorator

    class MyClass(object):
        @method_decorator(login_required)
        def my_view(self, request):
            pass

或者：

    from django.utils.decorators import method_decorator

    login_required_m = method_decorator(login_required)

    class MyClass(object):
        @login_required_m
        def my_view(self, request):
            pass

对于那些一直关注开发主干的人，这个变更也适用于自 1.1 版以来引入的其他装饰器，包括 `csrf_protect`、`cache_control` 和使用 `decorator_from_middleware` 创建的任何装饰器。

### `if` 标签的变更

由于 `if` 模板标签中的新功能，它不再接受 'and'、'or' 和 'not' 作为有效的 变量 名称。以前，这些字符串可以用作变量名。现在，关键字状态始终受到强制执行，因此模板代码如 `{% if not %}` 或 `{% if and %}` 将引发 `TemplateSyntaxError`。此外，`in` 是一个新关键字，因此在此标签中不是有效的变量名。

### `LazyObject`

`LazyObject` 是一个未记录但经常使用的实用类，用于懒惰地包装其他未知类型的对象。

在 Django 1.1 及更早版本中，它以一种非标准的方式处理内省，依赖于被包装的对象实现一个名为 `get_all_members()` 的公共方法。由于这可能会导致名称冲突，因此已更改为使用标准的 Python 内省方法，涉及 `__members__` 和 `__dir__()`。

如果你在自己的代码中使用了 `LazyObject` 并为被包装的对象实现了 `get_all_members()` 方法，你需要进行一些更改：

首先，如果你的类对内省没有特殊要求（即，你没有实现 `__getattr__()` 或其他允许通过正常机制无法发现的属性的方法），你可以简单地删除 `get_all_members()` 方法。`LazyObject` 上的默认实现会处理得当。

如果你对内省有更复杂的要求，首先将 `get_all_members()` 方法重命名为 `__dir__()`。这是 Python 2.6 及更高版本的标准内省方法。如果你需要支持早于 2.6 版本的 Python，请将以下代码添加到类中：

    __members__ = property(lambda self: self.__dir__())

### 模型实例上的 `__dict__`

在历史上，模型实例的 `__dict__` 属性仅包含与模型上的字段对应的属性。

为了支持多个数据库配置，Django 1.2 添加了一个 `_state` 属性到对象实例中。这个属性将出现在模型实例的 `__dict__` 中。如果你的代码依赖于遍历 `__dict__` 来获取字段列表，现在必须准备好处理或过滤掉 `_state` 属性。

### 测试运行器退出状态码

测试运行器（`tests/runtests.py` 和 `python manage.py test`）的退出状态码不再代表失败测试的数量，因为失败 256 个或更多测试会导致错误的退出状态码。现在测试运行器的退出状态码为 0 表示成功（没有失败测试），为 1 表示任何数量的测试失败。如果需要，可以在测试运行器的输出末尾找到测试失败的数量。

### Cookie 编码

To fix bugs with cookies in Internet Explorer, Safari, and possibly other browsers, our encoding of cookie values was changed so that the comma and semicolon are treated as non-safe characters, and are therefore encoded as `\054` and `\073` respectively. This could produce backwards incompatibilities, especially if you are storing comma or semi-colon in cookies and have JavaScript code that parses and manipulates cookie values client-side.

### `ModelForm.is_valid()` 和 `ModelForm.errors`

ModelForms 的大部分验证工作已经移到了模型级别。因此，第一次调用 `ModelForm.is_valid()`，访问 `ModelForm.errors` 或以其他方式触发表单验证时，你的模型将被原地清理。这个转换以前是在模型保存时发生的。如果你需要一个未修改的模型实例，你应该将一个副本传递给 `ModelForm` 构造函数。

### 在 MySQL 上的 `BooleanField`

In previous versions of Django, a model's `BooleanField` under MySQL would return its value as either `1` or `0`, instead of `True` or `False`; for most people this wasn't a problem because `bool` is a subclass of `int` in Python. In Django 1.2, however, `BooleanField` on MySQL correctly returns a real `bool`. The only time this should ever be an issue is if you were expecting the `repr` of a `BooleanField` to print `1` or `0`.

### 对于 FormSets 中 `max_num` 的解释变更

作为对 FormSets 处理的增强的一部分，`max_num` 参数在 django.forms.formsets.formset_factory() 和 django.forms.models.modelformset_factory() 函数中的默认值和解释略有变化。这个变更也影响了内联管理对象的 `max_num` 参数的使用方式。

以前，`max_num` 的默认值是 `0` （零）。FormSets 然后使用 `max_num` 的布尔值来确定是否要对生成的表单数量设置限制。默认值 `0` 意味着在 FormSet 中没有默认限制的表单数量。

从 1.2 版本开始，`max_num` 的默认值已更改为 `None`，并且 FormSets 将区分 `None` 和 `0` 之间的值。`None` 表示不限制表单数量；`0` 表示最多允许 0 个表单。这并不一定意味着不会显示任何表单 - 请参阅 ModelFormSet 文档 获取更多详细信息。

如果你手动指定了 `0` 作为 `max_num` 的值，你需要更新你的 FormSet 和/或管理定义。

See also

在管理中使用 JavaScript 辅助处理内联相关对象。

### `email_re`

一个未记录的用于验证电子邮件地址的正则表达式已从 `django.form.fields` 移动到了 `django.core.validators`。如果你在使用它，你需要更新你的导入。

## 在 1.2 中被废弃的功能

最后，Django 1.2 弃用了一些早期版本的功能。这些功能仍然受支持，但将在接下来的几个版本周期内逐步淘汰。

使用以下任何功能的代码将在 Django 1.2 中引发 `PendingDeprecationWarning`。这个警告默认情况下会被忽略，但可以使用 Python 的 `warnings` 模块来打开它，或者通过使用 `-Wd` 或 `-Wall` 标志来运行 Python 来启用它。

在 Django 1.3 中，这些警告将变为 `DeprecationWarning`，它不会被忽略。在 Django 1.4 中，对这些功能的支持将完全移除。

See also

有关更多详细信息，请参阅文档中的 Django 发布过程 和 弃用时间表。

### 指定数据库

在 Django 1.2 之前，Django 使用了许多设置来控制访问单个数据库。 Django 1.2 引入了对多数据库的支持，因此定义数据库设置的方式发生了变化。

任何现有的 Django 设置文件将继续按预期工作，直到 Django 1.4 。在此之前，旧式数据库设置将自动转换为新式格式。

在旧式（1.2 版之前）的格式中，你的设置文件中有许多 `DATABASE_` 设置。例如：

    DATABASE_NAME = "test_db"
    DATABASE_ENGINE = "postgresql_psycopg2"
    DATABASE_USER = "myusername"
    DATABASE_PASSWORD = "s3krit"

这些设置现在在名为 `DATABASES` 的字典中。字典中的每个条目对应一个单独的数据库连接，名称为 `'default'` 描述了默认的数据库连接。设置的名称也已经缩短。之前的示例设置现在会像这样：

    DATABASES = {
        "default": {
            "NAME": "test_db",
            "ENGINE": "django.db.backends.postgresql_psycopg2",
            "USER": "myusername",
            "PASSWORD": "s3krit",
        }
    }

这影响了以下设置：

旧设置 | 新设置
--- | ---
`DATABASE_ENGINE` | `ENGINE`
`DATABASE_HOST` | `HOST`
`DATABASE_NAME` | `NAME`
`DATABASE_OPTIONS` | `OPTIONS`
`DATABASE_PASSWORD` | `PASSWORD`
`DATABASE_PORT` | `PORT`
`DATABASE_USER` | `USER`
`TEST_DATABASE_CHARSET` | `TEST_CHARSET`
`TEST_DATABASE_COLLATION` | `TEST_COLLATION`
`TEST_DATABASE_NAME` | `TEST_NAME`

如果你使用所选择的数据库后端手动创建了数据库连接，这些更改也是必需的，可以使用 `DatabaseWrapper()`。

除了结构的变更，Django 1.2 还移除了内置数据库后端的特殊处理。现在，所有的数据库后端都必须使用完全限定的模块名来指定（例如，`django.db.backends.postgresql_psycopg2`，而不仅仅是 `postgresql_psycopg2`）。

### `postgresql` 数据库后端

`psycopg1` 库自 2005 年 10 月以来没有更新。因此，使用这个库的 `postgresql` 数据库后端已经被弃用。

如果你目前正在使用 `postgresql` 后端，你应该迁移到使用 `postgresql_psycopg2` 后端。要更新你的代码，安装 `psycopg2` 库，并将 `ENGINE` 设置更改为使用 `django.db.backends.postgresql_psycopg2`。

### CSRF 响应重写中间件

`CsrfResponseMiddleware`，自动在传出页面的 `POST` 表单中插入 CSRF 令牌的中间件，已被弃用，推荐使用模板标签方法（见上文），并将在 Django 1.4 中完全移除。同样，包含了 `CsrfResponseMiddleware` 和 `CsrfViewMiddleware` 功能的 `CsrfMiddleware` 也已被弃用。

此外，CSRF 模块已从 contrib 转移到核心，旧的导入已被弃用，如升级说明中所述。

已删除文档

当前 Django 文档中已删除了升级说明。请参考 Django 1.3 或更早版本的文档以查找这些说明。

### `SMTPConnection`

`SMTPConnection` 类已被弃用，以支持通用的电子邮件后端 API。旧代码中明确实例化 `SMTPConnection` 实例的方式已被弃用：

    from django.core.mail import SMTPConnection

    connection = SMTPConnection()
    messages = get_notification_email()
    connection.send_messages(messages)

...should now call `get_connection()` to instantiate a generic email connection:

    from django.core.mail import get_connection

    connection = get_connection()
    messages = get_notification_email()
    connection.send_messages(messages)

根据 `EMAIL_BACKEND` 设置的值，这可能不会返回一个 SMTP 连接。如果你明确需要一个用于发送电子邮件的 SMTP 连接，可以显式请求一个 SMTP 连接：

    from django.core.mail import get_connection

    connection = get_connection("django.core.mail.backends.smtp.EmailBackend")
    messages = get_notification_email()
    connection.send_messages(messages)

If your call to construct an instance of `SMTPConnection` required additional arguments, those arguments can be passed to the `get_connection()` call:

    connection = get_connection(
        "django.core.mail.backends.smtp.EmailBackend", hostname="localhost", port=1234
    )

### 用户消息 API

通过 `user.message_set.create` 在用户 `Message` 模型中存储消息的 API 已被弃用，并将根据标准的 发布流程 在 Django 1.4 中移除。

要升级你的代码，你需要替换所有这样的实例：

    user.message_set.create("a message")

... 替换为以下内容：

    from django.contrib import messages

    messages.add_message(request, messages.INFO, "a message")

此外，如果你使用这个方法，你需要替换以下内容：

    for message in user.get_and_delete_messages():
        ...

... 替换为：

    from django.contrib import messages

    for message in messages.get_messages(request):
        ...

有关更多信息，请参阅完整的 消息文档。你应该立即开始更新你的代码以使用新的 API。

### 日期格式辅助函数

`django.utils.translation.get_date_formats()` 和 `django.utils.translation.get_partial_date_formats()` 已被弃用，推荐使用适当的调用 `django.utils.formats.get_format()`，当 `USE_L10N` 设置为 `True` 时，它是区域感知的，并在设置为 `False` 时回退到默认设置。

要获得不同的日期格式，而不是编写这样的代码：

    from django.utils.translation import get_date_formats

    date_format, datetime_format, time_format = get_date_formats()

... 使用：

    from django.utils import formats

    date_format = formats.get_format("DATE_FORMAT")
    datetime_format = formats.get_format("DATETIME_FORMAT")
    time_format = formats.get_format("TIME_FORMAT")

或者，在直接格式化日期值时：

    from django.utils import formats

    value_formatted = formats.date_format(value, "DATETIME_FORMAT")

同样适用于 `django.forms.fields` 中找到的全局变量：

- `DEFAULT_DATE_INPUT_FORMATS`

- `DEFAULT_TIME_INPUT_FORMATS`

- `DEFAULT_DATETIME_INPUT_FORMATS`

使用 `django.utils.formats.get_format()` 获取适当的格式。

### 基于函数的测试运行器

Django 1.2 更改了测试运行工具以使用基于类的方法。旧式的基于函数的测试运行工具仍然可以工作，但应该更新为使用新的 基于类的运行工具。

### `django.contrib.syndication.feeds` 中的 `Feed`

`django.contrib.syndication.feeds.Feed` 类已被 `django.contrib.syndication.views.Feed` 类替代。旧的 `feeds.Feed` 类已被弃用，并将在 Django 1.4 中移除。

新的类具有几乎相同的 API，但允许将实例用作视图。例如，考虑以下 URLconf 中使用旧框架的示例：

    from django.conf.urls.defaults import *
    from myproject.feeds import LatestEntries, LatestEntriesByCategory

    feeds = {
        "latest": LatestEntries,
        "categories": LatestEntriesByCategory,
    }

    urlpatterns = patterns(
        "",
        # ...
        (
            r"^feeds/(?P<url>.*)/$",
            "django.contrib.syndication.views.feed",
            {"feed_dict": feeds},
        ),
        # ...
    )

使用新的 Feed 类，这些 feed 可以直接作为视图部署：

    from django.conf.urls.defaults import *
    from myproject.feeds import LatestEntries, LatestEntriesByCategory

    urlpatterns = patterns(
        "",
        # ...
        (r"^feeds/latest/$", LatestEntries()),
        (r"^feeds/categories/(?P<category_id>\d+)/$", LatestEntriesByCategory()),
        # ...
    )

如果你当前使用 `feed()` 视图，那么 `LatestEntries` 类通常不需要进行修改，除非它是新的 `Feed` 类的子类。唯一的例外是如果 Django 自动计算要用于渲染 feed 的描述和标题元素的模板名称（如果你没有指定 `title_template` 和 `description_template` 属性）。你应该确保始终指定 `title_template` 和 `description_template` 属性，或提供 `item_title()` 和 `item_description()` 方法。

然而，`LatestEntriesByCategory` 使用了 `get_object()` 方法，并通过 `bits` 参数指定要显示的特定类别。在新的 `Feed` 类中，`get_object()` 方法接受一个 `request` 和来自 URL 的参数，所以它会像这样：

    from django.contrib.syndication.views import Feed
    from django.shortcuts import get_object_or_404
    from myproject.models import Category

    class LatestEntriesByCategory(Feed):
        def get_object(self, request, category_id):
            return get_object_or_404(Category, id=category_id)

        # ...

另外，`Feed` 类上的 `get_feed()` 方法现在接受不同的参数，如果你直接使用 `Feed` 类，这可能会影响你。现在它不仅接受可选的 `url` 参数，还接受两个参数：它自己的 `get_object()` 方法返回的对象以及当前的 `request` 对象。

为了考虑到 `Feed` 类不会为每个请求初始化，现在默认情况下 `__init__()` 方法不接受任何参数。以前它会接受来自 URL 的 `slug` 和 `request` 对象作为参数。

根据 RSS 最佳实践，RSS 订阅现在将包含一个 `atom:link` 元素。你可能需要更新你的测试以考虑这一点。

有关更多信息，请参阅完整的 syndication 框架文档。

### 技术性消息 ID

在版本 1.1 之前，Django 使用技术性的消息 ID 来提供本地化者翻译日期和时间格式的可能性。它们是可翻译的 翻译字符串，可以通过它们都是大写字母来识别（例如 `DATETIME_FORMAT`, `DATE_FORMAT`, `TIME_FORMAT`）。它们已被弃用，推荐使用新的 本地格式化 基础设施，允许本地化者在相应的 `django/conf/locale/<locale name>/` 目录中的 `formats.py` 文件中指定这些信息。

### GeoDjango

To allow support for multiple databases, the GeoDjango database internals were changed substantially. The largest backwards-incompatible change is that the module `django.contrib.gis.db.backend` was renamed to `django.contrib.gis.db.backends`, where the full-fledged spatial database backends now exist. The following sections provide information on the most-popular APIs that were affected by these changes.

#### `SpatialBackend`

Prior to the creation of the separate spatial backends, the `django.contrib.gis.db.backend.SpatialBackend` object was provided as an abstraction to introspect on the capabilities of the spatial database. All of the attributes and routines provided by `SpatialBackend` are now a part of the `ops` attribute of the database backend.

旧模块 `django.contrib.gis.db.backend` 仍然提供了向后兼容的访问 `SpatialBackend` 对象的方式，它只是默认空间数据库连接的 `ops` 模块的别名。

依赖于 `django.contrib.gis.db.backend` 中的未记录模块和对象，而不是 `SpatialBackend` 提供的抽象的用户需要修改他们的代码。例如，在 1.1 及以下版本中可以正常工作的以下导入：

    from django.contrib.gis.db.backend.postgis import PostGISAdaptor

需要进行更改：

    from django.db import connection

    PostGISAdaptor = connection.ops.Adapter

#### `SpatialRefSys` 和 `GeometryColumns` 模型

在 GeoDjango 的早期版本中，`django.contrib.gis.db.models` 包含了用于查询 OGC 空间元数据表 `spatial_ref_sys` 和 `geometry_columns` 的 `SpatialRefSys` 和 `GeometryColumns` 模型。

尽管仍然提供这些别名，但它们仅适用于 默认 数据库连接，并且仅在默认连接使用受支持的空间数据库后端时存在。

Note

Because the table structure of the OGC spatial metadata tables differs across spatial databases, the `SpatialRefSys` and `GeometryColumns` models can no longer be associated with the `gis` application name. Thus, no models will be returned when using the `get_models` method in the following example:

    >>> from django.db.models import get_app, get_models
    >>> get_models(get_app("gis"))
    []

要获取与你的空间数据库匹配的正确的 `SpatialRefSys` 和 `GeometryColumns`，请使用空间后端提供的方法：

>     >>> from django.db import connections
>     >>> SpatialRefSys = connections["my_spatialite"].ops.spatial_ref_sys()
>     >>> GeometryColumns = connections["my_postgis"].ops.geometry_columns()

Note

当使用从 `spatial_ref_sys()` 和 `geometry_columns()` 方法返回的模型时，仍然需要在查询非默认连接时使用正确的数据库别名。换句话说，为了确保上面示例中的模型使用正确的数据库：

    sr_qs = SpatialRefSys.objects.using("my_spatialite").filter(...)
    gc_qs = GeometryColumns.objects.using("my_postgis").filter(...)

### 语言代码 `no`

目前使用的挪威博克马尔语的语言代码 `no` 正在被更常见的语言代码 `nb` 所取代。

### 基于函数的模板加载器

Django 1.2 将模板加载机制更改为使用基于类的方法。旧式基于函数的模板加载器仍然可以工作，但应该更新为使用新的基于类的模板加载器。