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

*2017 年 12 月 2 日*

欢迎来到 Django 2.0 版本!

这些发布说明涵盖了 [新特性](#whats-new-2-0)，以及从 Django 1.11 或更早版本升级时需要注意的一些 [不兼容的变更](#backwards-incompatible-2-0)。我们已经 [删除了一些已经达到了弃用周期末尾的功能](#removed-features-2-0)，并且我们已经 [开始了一些功能的弃用过程](#deprecated-features-2-0)。

这个发布版本开始使用了 Django 的一种 [松散形式的语义版本](/zh-hans/4.2/internals/release-process/#internal-release-cadence)，但并没有出现与 2.0 版本发布相符的重大不兼容变更。升级应该与过去的功能发布相似的努力。

如果你要更新现有的项目，请看 [如何将 Django 更新至新的版本](/zh-hans/4.2/howto/upgrade-version/) 指南。

## Python 兼容性

Django 2.0 支持 Python 3.4、3.5、3.6 和 3.7。我们 **强烈建议** 并且只官方支持每个系列的最新版本。

Django 1.11.x 系列是支持 Python 2.7 版本的最后一个系列。

Django 2.0 将是最后一个支持 Python 3.4 的发布系列。如果您计划在 Django 2.0 的生命周期结束后（2019 年 4 月）继续使用 Python 3.4，请改用 Django 1.11 LTS（支持到 2020 年 4 月）代替。请注意，Python 3.4 的生命周期将于 2019 年 3 月结束。

## 对于较旧版本的 Django 的第三方库支持

在 Django 2.0 发布之后，我们建议第三方应用程序的作者停止支持 1.11 之前的所有 Django 版本。在那个时候，你应该能够使用 `python -Wd` 运行你包的测试，以便弃用警告会出现。在进行弃用警告修复后，你的应用程序应该与 Django 2.0 兼容。

## Django 2.0 新特性

### 简化 URL 路由语法

新版本 [`django.urls.path()`](/zh-hans/4.2/ref/urls/#django.urls.path) 函数使用更简单易读的 URL 路由语法。一个来自 Django 旧版本的例子：

```
url(r"^articles/(?P<year>[0-9]{4})/$", views.year_archive),
```

可以写成：

```
path("articles/<int:year>/", views.year_archive),
```

新版本语法支持对 URL 参数的强制类型转换。在这个例子中，视图将会以数字类型接收参数 `year` 而不是以字符串类型。而且 URLs 的匹配限制也减少了。例如，因为参数 year 并没有像正则表达式中那样明确限制为四位数，year 为 10000 也会匹配成功。

旧版本中的 `django.conf.urls.url()` 函数现在可以在 [`django.urls.re_path()`](/zh-hans/4.2/ref/urls/#django.urls.re_path) 中获取。前者依然保留，向后兼容，并没有立即弃用。旧版本中的 `django.conf.urls.include()` 函数现在可以从 `django.urls` 中导入，这样你就可以在 URLconfs 中使用 `from django.urls import include, path, re_path` 。

重新编写的文档 [URL调度器](/zh-hans/4.2/topics/http/urls/) 涵盖了新的语法并且提供了更多的细节。

### `contrib.admin` 针对移动设备的优化改进

新版本的 admin 可以响应和支持所有主流移动设备。较旧的浏览器可能会遇到不同程度的功能降低。

### Window 表达式

新的 [`Window`](/zh-hans/4.2/ref/models/expressions/#django.db.models.expressions.Window) 表达式允许在查询集上添加一个 `OVER` 子句。你可以在这个表达式中使用 [窗口函数](/zh-hans/4.2/ref/models/database-functions/#window-functions) 和 [聚合函数](/zh-hans/4.2/ref/models/querysets/#aggregation-functions)。

### 次要特性

#### [`django.contrib.admin`](/zh-hans/4.2/ref/contrib/admin/#module-django.contrib.admin)

- 新的 [`ModelAdmin.autocomplete_fields`](/zh-hans/4.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields) 属性和 [`ModelAdmin.get_autocomplete_fields()`](/zh-hans/4.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_autocomplete_fields) 方法允许在 `ForeignKey` 和 `ManyToManyField` 上使用 [Select2](https://select2.org/) 搜索小部件。

#### [`django.contrib.auth`](/zh-hans/4.2/topics/auth/#module-django.contrib.auth)

- PBKDF2 密码散列器的默认迭代计数从 36,000 增加到 100,000。

#### [`django.contrib.gis`](/zh-hans/4.2/ref/contrib/gis/#module-django.contrib.gis)

- 增加了 [`AsGeoJSON`](/zh-hans/4.2/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.AsGeoJSON) 函数、 [`GeoHash`](/zh-hans/4.2/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.GeoHash) 函数、[`IsValid`](/zh-hans/4.2/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.IsValid) 函数、[`isvalid`](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#std-fieldlookup-isvalid) 查找、以及 [distance lookups](/zh-hans/4.2/ref/contrib/gis/geoquerysets/#distance-lookups) 对 MySQL 的支持。
- 添加了 PostGIS 和 SpatiaLite 支持的两个函数 [`Azimuth`](/zh-hans/4.2/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.Azimuth) 和 [`LineLocatePoint`](/zh-hans/4.2/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.LineLocatePoint)。
- 现在所有从 GeoJSON 导入的 [`GEOSGeometry`](/zh-hans/4.2/ref/contrib/gis/geos/#django.contrib.gis.geos.GEOSGeometry) 都设置了其 SRID。
- 添加了 [`OSMWidget.default_zoom`](/zh-hans/4.2/ref/contrib/gis/forms-api/#django.contrib.gis.forms.widgets.OSMWidget.default_zoom) 属性来自定义地图的默认缩放级别。
- 通过 [`metadata`](/zh-hans/4.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALRaster.metadata)、[`info`](/zh-hans/4.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALRaster.info) 和 [`metadata`](/zh-hans/4.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALBand.metadata) 属性，使栅格数据的元数据可读可编辑。
- 允许使用 `papsz_options` 将 driver-specific creation options 传递给 [`GDALRaster`](/zh-hans/4.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALRaster) 对象。
- 允许在 GDAL 的内部虚拟文件系统中创建 [`GDALRaster`](/zh-hans/4.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALRaster) 对象。现在可以将栅格数据从内存中的二进制数据 [创建和转换](/zh-hans/4.2/ref/contrib/gis/gdal/#gdal-raster-vsimem)。
- 新的 [`GDALBand.color_interp()`](/zh-hans/4.2/ref/contrib/gis/gdal/#django.contrib.gis.gdal.GDALBand.color_interp) 方法返回了该波段的颜色解释。

#### [`django.contrib.postgres`](/zh-hans/4.2/ref/contrib/postgres/#module-django.contrib.postgres)

- 对于 [`ArrayAgg`](/zh-hans/4.2/ref/contrib/postgres/aggregates/#django.contrib.postgres.aggregates.ArrayAgg)，新的 `distinct` 参数确定连接的值是否是不同的。
- 新的 [`RandomUUID`](/zh-hans/4.2/ref/contrib/postgres/functions/#django.contrib.postgres.functions.RandomUUID) 数据库函数返回版本 4 的 UUID。它需要使用 PostgreSQL 的 `pgcrypto` 扩展，可以通过新的 [`CryptoExtension`](/zh-hans/4.2/ref/contrib/postgres/operations/#django.contrib.postgres.operations.CryptoExtension) 迁移操作来激活。
- [`django.contrib.postgres.indexes.GinIndex`](/zh-hans/4.2/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.GinIndex) 现在支持 `fastupdate` 和 `gin_pending_list_limit` 参数。
- 新的 [`GistIndex`](/zh-hans/4.2/ref/contrib/postgres/indexes/#django.contrib.postgres.indexes.GistIndex) 类允许在数据库中创建 `GiST` 索引。新的 [`BtreeGistExtension`](/zh-hans/4.2/ref/contrib/postgres/operations/#django.contrib.postgres.operations.BtreeGistExtension) 迁移操作安装了 `btree_gist` 扩展，以添加对不是内置的操作符类的支持。
- [`inspectdb`](/zh-hans/4.2/ref/django-admin/#django-admin-inspectdb) 现在可以内省 `JSONField` 和各种 `RangeField` （必须将 `django.contrib.postgres` 添加到 `INSTALLED_APPS` 中）。

#### [`django.contrib.sitemaps`](/zh-hans/4.2/ref/contrib/sitemaps/#module-django.contrib.sitemaps)

- 在 [`GenericSitemap`](/zh-hans/4.2/ref/contrib/sitemaps/#django.contrib.sitemaps.GenericSitemap) 构造函数中添加了 `protocol` 关键字参数。

#### 缓存

- `cache.set_many()` 现在返回一个未能插入的键的列表。对于内置的后端，失败的插入只会发生在 memcached 上。

#### 文件存储

- [`File.open()`](/zh-hans/4.2/ref/files/file/#django.core.files.File.open) 可以作为上下文管理器使用，例如 `with file.open() as f:`。

#### 表单

- 对于 [`SplitDateTimeWidget`](/zh-hans/4.2/ref/forms/widgets/#django.forms.SplitDateTimeWidget) 和 [`SplitHiddenDateTimeWidget`](/zh-hans/4.2/ref/forms/widgets/#django.forms.SplitHiddenDateTimeWidget)，新的 `date_attrs` 和 `time_attrs` 参数允许指定不同的 HTML 属性用于 `DateInput` 和 `TimeInput` （或隐藏）子部件。
- 新的 [`Form.errors.get_json_data()`](/zh-hans/4.2/ref/forms/api/#django.forms.Form.errors.get_json_data) 方法返回适用于包含在 JSON 响应中的表单错误的字典。

#### 通用视图

- 新属性 [`ContextMixin.extra_context`](/zh-hans/4.2/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.extra_context) 允许在 `View.as_view()` 添加上下文。

#### 管理命令

- [`inspectdb`](/zh-hans/4.2/ref/django-admin/#django-admin-inspectdb) 现在将 MySQL 的无符号整数列翻译为 `PositiveIntegerField` 或 `PositiveSmallIntegerField`。
- 新的 [`makemessages --add-location`](/zh-hans/4.2/ref/django-admin/#cmdoption-makemessages-add-location) 选项控制 `.po` 文件中的注释格式。
- [`loaddata`](/zh-hans/4.2/ref/django-admin/#django-admin-loaddata) 现在可以从标准输入中 [读取数据](/zh-hans/4.2/ref/django-admin/#loading-fixtures-stdin)。
- 新的 [`diffsettings --output`](/zh-hans/4.2/ref/django-admin/#cmdoption-diffsettings-output) 选项允许以统一的差异格式格式化输出。
- 在 Oracle 上，[`inspectdb`](/zh-hans/4.2/ref/django-admin/#django-admin-inspectdb) 现在可以内省 `AutoField`，如果列被创建为标识列（identity column）。
- 在 MySQL 上，[`dbshell`](/zh-hans/4.2/ref/django-admin/#django-admin-dbshell) 现在支持客户端端的 TLS 证书。

#### 迁移

- 新的 [`squashmigrations --squashed-name`](/zh-hans/4.2/ref/django-admin/#cmdoption-squashmigrations-squashed-name) 选项允许命名合并后的迁移。

#### 模型

- 新的 [`StrIndex`](/zh-hans/4.2/ref/models/database-functions/#django.db.models.functions.StrIndex) 数据库函数用于查找一个字符串在另一个字符串中的起始索引。
- 在 Oracle 上，现在会将 `AutoField` 和 `BigAutoField` 创建为 [标识列](https://docs.oracle.com/en/database/oracle/oracle-database/21/drdaa/intro-to-tools-and-products-supporting-migraiton.html#GUID-14E4817B-F3BC-4D99-B471-A0ACDC303CC9)。
- [`QuerySet.iterator()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.iterator) 的新参数 `chunk_size` 控制在从数据库流式传输结果时由 Python 数据库客户端提取的行数。对于不支持服务器端游标的数据库，它控制 Django 从数据库适配器提取的结果数量。
- [`QuerySet.earliest()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.earliest)、[`QuerySet.latest()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.latest) 和 [`Meta.get_latest_by`](/zh-hans/4.2/ref/models/options/#django.db.models.Options.get_latest_by) 现在允许按多个字段排序。
- 新增了 [`ExtractQuarter`](/zh-hans/4.2/ref/models/database-functions/#django.db.models.functions.ExtractQuarter) 函数，用于从 [`DateField`](/zh-hans/4.2/ref/models/fields/#django.db.models.DateField) 和 [`DateTimeField`](/zh-hans/4.2/ref/models/fields/#django.db.models.DateTimeField) 中提取季度，并通过 [`quarter`](/zh-hans/4.2/ref/models/querysets/#std-fieldlookup-quarter) 查找公开。
- 新增了 [`TruncQuarter`](/zh-hans/4.2/ref/models/database-functions/#django.db.models.functions.TruncQuarter) 函数，用于将 [`DateField`](/zh-hans/4.2/ref/models/fields/#django.db.models.DateField) 和 [`DateTimeField`](/zh-hans/4.2/ref/models/fields/#django.db.models.DateTimeField) 截断到季度的第一天。
- 为基于类的索引添加了 [`db_tablespace`](/zh-hans/4.2/ref/models/indexes/#django.db.models.Index.db_tablespace) 参数。
- 如果数据库支持原生的持续时间字段（Oracle 和 PostgreSQL），[`Extract`](/zh-hans/4.2/ref/models/database-functions/#django.db.models.functions.Extract) 现在可以与 [`DurationField`](/zh-hans/4.2/ref/models/fields/#django.db.models.DurationField) 一起使用。
- 新增了 `of` 参数到 [`QuerySet.select_for_update()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.select_for_update)，在 PostgreSQL 和 Oracle 上支持，可以锁定特定表中的行，而不是所有选定的表。这在特别是当 [`select_for_update()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.select_for_update) 与 [`select_related()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.select_related) 结合使用时可能会有所帮助。
- [`QuerySet.in_bulk()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.in_bulk) 的新参数 `field_name` 允许根据任何唯一模型字段获取结果。
- [`CursorWrapper.callproc()`](/zh-hans/4.2/topics/db/sql/#django.db.models.CursorWrapper.callproc) 现在可以接受一个可选的关键字参数字典，如果后端支持此功能。Django 内置的后端中，只有 Oracle 支持这个功能。
- 新的 [`connection.execute_wrapper()`](/zh-hans/4.2/topics/db/instrumentation/#django.db.backends.base.DatabaseWrapper.execute_wrapper) 方法允许 [在执行数据库查询时安装包装器](/zh-hans/4.2/topics/db/instrumentation/)。
- 内置聚合函数的新 `filter` 参数允许在同一字段或关系上的多个聚合中 [添加不同的条件](/zh-hans/4.2/ref/models/conditional-expressions/#conditional-aggregation)。
- 在 [`Meta.ordering`](/zh-hans/4.2/ref/models/options/#django.db.models.Options.ordering) 中添加了对表达式的支持。
- [`QuerySet.values_list()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.values_list) 的新参数 `named` 允许将结果作为命名元组获取。
- 新的 [`FilteredRelation`](/zh-hans/4.2/ref/models/querysets/#django.db.models.FilteredRelation) 类允许在查询集中添加一个 `ON` 子句。

#### 分页

- 添加了 [`Paginator.get_page()`](/zh-hans/4.2/ref/paginator/#django.core.paginator.Paginator.get_page)，以提供处理无效页码的文档化模式。

#### 请求和响应

- [`runserver`](/zh-hans/4.2/ref/django-admin/#django-admin-runserver) Web 服务器支持 HTTP 1.1。

#### 模板

- 为了增加第三方应用程序中 [`Engine.get_default()`](/zh-hans/4.2/ref/templates/api/#django.template.Engine.get_default) 的实用性，如果在 `TEMPLATES` 中配置了多个 `DjangoTemplates` 引擎，它现在将返回第一个引擎，而不是引发 `ImproperlyConfigured` 异常。
- 现在自定义模板标签可以接受仅限关键字的参数。

#### 测试

- 向 [`LiveServerTestCase`](/zh-hans/4.2/topics/testing/tools/#django.test.LiveServerTestCase) 添加了多线程支持。
- 添加了允许自定义 Oracle 测试表空间参数的设置：[`DATAFILE_SIZE`](/zh-hans/4.2/ref/settings/#std-setting-DATAFILE_SIZE)、[`DATAFILE_TMP_SIZE`](/zh-hans/4.2/ref/settings/#std-setting-DATAFILE_TMP_SIZE)、[`DATAFILE_EXTSIZE`](/zh-hans/4.2/ref/settings/#std-setting-DATAFILE_EXTSIZE) 和 [`DATAFILE_TMP_EXTSIZE`](/zh-hans/4.2/ref/settings/#std-setting-DATAFILE_TMP_EXTSIZE)。

#### 验证器

- 新的 [`ProhibitNullCharactersValidator`](/zh-hans/4.2/ref/validators/#django.core.validators.ProhibitNullCharactersValidator) 在 [`CharField`](/zh-hans/4.2/ref/forms/fields/#django.forms.CharField) 表单字段及其子类的输入中禁止使用空字符。空字符输入是由于漏洞扫描工具而观察到的。大多数数据库会悄悄地丢弃空字符，但是当尝试将空字符保存到 PostgreSQL 的 char/text 字段时，psycopg2 2.7+ 会引发异常。

## 2.0 版本的不向后兼容变更

### 在某些地方移除了对字节字符串的支持

为了支持原生的 Python 2 字符串，旧版本的 Django 必须同时接受字节字符串和 Unicode 字符串。现在 Python 2 的支持已被移除，字节字符串应该只出现在输入/输出边界（例如处理二进制字段或 HTTP 流）附近。您可能需要更新您的代码，以将字节字符串的使用限制到最低，因为 Django 不再在某些代码路径中接受字节字符串。Python 的 [`-b`](https://docs.python.org/3/using/cmdline.html#cmdoption-b) 选项可能有助于检测代码中的这种错误。

例如，现在 `reverse()` 在将接收到的 `args` 和 `kwargs` 放置在 URL 之前，使用 `str()` 而不是 `force_text()` 来强制转换它们。对于字节字符串，这会创建一个带有不希望的 `b` 前缀以及额外引号的字符串（`str(b'foo')` 是 `"b'foo'"`）。为了适应这种变化，在将字节字符串传递给 `reverse()` 之前，请调用 `decode()`。

### 数据库后端 API

本节介绍了第三方数据库后端可能需要的更改。

- 现在，`DatabaseOperations.datetime_cast_date_sql()`、`datetime_cast_time_sql()`、`datetime_trunc_sql()`、`datetime_extract_sql()` 和 `date_interval_sql()` 方法仅返回执行操作的 SQL，而不再返回 SQL 和参数列表。
- 第三方数据库后端应该添加一个名为 `DatabaseWrapper.display_name` 的属性，该属性包含您的后端适用于的数据库名称。Django 可能会在各种消息中使用它，例如系统检查中。
- `SchemaEditor._alter_column_type_sql()` 的第一个参数现在是 `model`，而不再是 `table`。
- `SchemaEditor._create_index_name()` 的第一个参数现在是 `table_name`，而不再是 `model`。
- 要启用 `FOR UPDATE OF` 支持，请设置 `DatabaseFeatures.has_select_for_update_of = True`。如果数据库要求 `OF` 的参数是列而不是表，请设置 `DatabaseFeatures.select_for_update_of_column = True`。
- 要启用对 [`Window`](/zh-hans/4.2/ref/models/expressions/#django.db.models.expressions.Window) 表达式的支持，请将 `DatabaseFeatures.supports_over_clause` 设置为 `True`。您可能需要自定义 `DatabaseOperations.window_start_rows_start_end()` 和/或 `window_start_range_start_end()` 方法。
- 第三方数据库后端应该添加一个名为 `DatabaseOperations.cast_char_field_without_max_length` 的属性，该属性指定在没有提供 `max_length` 参数的情况下，在 [`Cast`](/zh-hans/4.2/ref/models/database-functions/#django.db.models.functions.Cast) 函数中将用于 `CharField` 的数据库数据类型。
- `DatabaseCreation._clone_test_db()` 和 `get_test_db_clone_settings()` 的第一个参数现在是 `suffix`，而不再是 ```number``（如果您希望为了一致性而在您的后端中重命名签名）。``django.test``` 现在也将这些值作为字符串而不是整数传递。
- 第三方数据库后端应该基于 `BaseDatabaseIntrospection` 中的存根添加一个名为 `DatabaseIntrospection.get_sequences()` 的方法。

### 不再支持 Oracle 11.2

Oracle 11.2 的上游支持将于 2020 年 12 月结束。 Django 1.11 将在 2020 年 4 月之前得到支持，几乎达到了这个日期。 Django 2.0 正式支持 Oracle 12.1 及更高版本。

### 默认的 MySQL 隔离级别为读已提交（read committed）

MySQL 的默认隔离级别，可重复读（repeatable read），在典型的 Django 使用中可能会导致数据丢失。为了防止这种情况并保持与其他数据库的一致性，现在默认的隔离级别是读提交（read committed）。如果需要，您可以使用 [`DATABASES`](/zh-hans/4.2/ref/settings/#std-setting-DATABASES) 设置来 [使用不同的隔离级别](/zh-hans/4.2/ref/databases/#mysql-isolation-level)。

### [`AbstractUser.last_name`](/zh-hans/4.2/ref/contrib/auth/#django.contrib.auth.models.User.last_name) 的 `max_length` 增加到了 150。

包含了 [`django.contrib.auth.models.User.last_name`](/zh-hans/4.2/ref/contrib/auth/#django.contrib.auth.models.User.last_name) 的迁移。如果您有一个从 `AbstractUser` 继承的自定义用户模型，您需要生成并应用一个数据库迁移来更新您的用户模型。

如果您想保留姓氏的 30 个字符限制，请使用自定义表单：

```
from django.contrib.auth.forms import UserChangeForm

class MyUserChangeForm(UserChangeForm):
    last_name = forms.CharField(max_length=30, required=False)
```

如果你想在管理中编辑用户时保留这个限制，请将 `UserAdmin.form` 设置为使用这个表单：

```
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

class MyUserAdmin(UserAdmin):
    form = MyUserChangeForm

admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
```

### 在切片之后，禁止使用 `QuerySet.reverse()` 和 `last()`。

在切片后调用 `QuerySet.reverse()` 或 `last()` 会导致意外的结果，因为切片是在重新排序后应用的。现在已禁止这样使用，例如：

```pycon
>>> Model.objects.all()[:2].reverse()
Traceback (most recent call last):
...
TypeError: Cannot reverse a query once a slice has been taken.
```

### 表单字段不再将可选参数作为位置参数接受

为了帮助防止由于表单字段参数顺序不正确而导致的运行时错误，内置表单字段的可选参数不再作为位置参数接受。例如：

```
forms.IntegerField(25, 10)
```

会引发异常，并且应该替换为：

```
forms.IntegerField(max_value=25, min_value=10)
```

### `call_command()` 验证它接收到的选项

`call_command()` 现在验证被调用的命令的参数解析器是否定义了传递给 `call_command()` 的所有选项。

对于使用非 `parser.add_argument()` 创建的选项的自定义管理命令，请在命令上添加一个名为 `stealth_options` 的属性：

```
class MyCommand(BaseCommand):
    stealth_options = ("option_name", ...)
```

### 索引不再接受位置参数

例子：

```
models.Index(["headline", "-pub_date"], "index_name")
```

会引发异常，并且应该替换为：

```
models.Index(fields=["headline", "-pub_date"], name="index_name")
```

### 现在在 SQLite 上启用了外键约束（Foreign key constraints）

如果尝试保存违反外键约束的现有模型实例，将会出现不兼容的后向变更（`IntegrityError: FOREIGN KEY constraint failed`）。

外键现在使用 `DEFERRABLE INITIALLY DEFERRED` 而不是 `DEFERRABLE IMMEDIATE` 来创建。因此，可能需要重新构建表以使用新的定义重新创建外键，特别是如果您使用了类似这样的模式：

```
from django.db import transaction

with transaction.atomic():
    Book.objects.create(author_id=1)
    Author.objects.create(id=1)
```

如果不将外键重新创建为 `DEFERRED`，那么由于现在强制执行外键约束，第一次的 `create()` 将会失败。

首先备份您的数据库！在升级到 Django 2.0 后，您可以使用类似以下脚本的方式重新构建表格：

```
from django.apps import apps
from django.db import connection

for app in apps.get_app_configs():
    for model in app.get_models(include_auto_created=True):
        if model._meta.managed and not (model._meta.proxy or model._meta.swapped):
            for base in model.__bases__:
                if hasattr(base, "_meta"):
                    base._meta.local_many_to_many = []
            model._meta.local_many_to_many = []
            with connection.schema_editor() as editor:
                editor._remake_table(model)
```

这个脚本尚未经过广泛测试，并且需要根据不同情况进行调整，比如多个数据库的情况。欢迎贡献改进。

另外，由于 SQLite 的表更改限制，禁止在事务中对被其他模型引用的模型或字段执行 [`RenameModel`](/zh-hans/4.2/ref/migration-operations/#django.db.migrations.operations.RenameModel) 和 [`RenameField`](/zh-hans/4.2/ref/migration-operations/#django.db.migrations.operations.RenameField) 操作。为了允许应用包含这些操作的迁移，您必须将 `Migration.atomic` 属性设置为 `False`。

### 杂项

- `SessionAuthenticationMiddleware` 类已被移除。自 Django 1.10 版本起，它不再提供任何功能，因为会话身份验证已无条件启用。
- 默认的 HTTP 错误处理程序（`handler404` 等）现在是可调用函数，而不再是点分 Python 路径字符串。Django 更倾向于可调用引用，因为它们提供更好的性能和调试体验。
- [`RedirectView`](/zh-hans/4.2/ref/class-based-views/base/#django.views.generic.base.RedirectView) 不再在 `pattern_name` 不存在时抑制 `NoReverseMatch`。
- 当 `USE_L10N` 关闭时，[`FloatField`](/zh-hans/4.2/ref/forms/fields/#django.forms.FloatField) 和 [`DecimalField`](/zh-hans/4.2/ref/forms/fields/#django.forms.DecimalField) 现在在验证过程中会尊重 [`DECIMAL_SEPARATOR`](/zh-hans/4.2/ref/settings/#std-setting-DECIMAL_SEPARATOR) 和 [`THOUSAND_SEPARATOR`](/zh-hans/4.2/ref/settings/#std-setting-THOUSAND_SEPARATOR)。例如，使用以下设置：

  ```
  USE_L10N = False
  USE_THOUSAND_SEPARATOR = True
  DECIMAL_SEPARATOR = ","
  THOUSAND_SEPARATOR = "."
  ```

  输入值 `"1.345"` 现在被转换为 `1345`，而不是 `1.345`。
- [`AbstractBaseUser`](/zh-hans/4.2/topics/auth/customizing/#django.contrib.auth.models.AbstractBaseUser) 的子类不再需要实现 `get_short_name()` 和 `get_full_name()`。（已删除引发 `NotImplementedError` 的基本实现。）如果实现了这些方法，`django.contrib.admin` 将使用它们，但不再要求它们。使用这些方法的第三方应用程序可能希望采用类似的方法。
- `FIRST_DAY_OF_WEEK` 和 `NUMBER_GROUPING` 格式设置现在在 JavaScript 和 JSON i18n 视图输出中保持为整数。
- [`assertNumQueries()`](/zh-hans/4.2/topics/testing/tools/#django.test.TransactionTestCase.assertNumQueries) 现在忽略连接配置查询。以前，如果一个测试打开了一个新的数据库连接，那些查询可能会被包括在 `assertNumQueries()` 计数中。
- Oracle 测试表空间的默认大小从 20M 增加到 50M，自动扩展的默认大小从 10M 增加到 25M 。
- 为了提高从数据库流式传输大型结果集的性能，[`QuerySet.iterator()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.iterator) 现在一次获取 2000 行，而不是 100 行。可以使用 `chunk_size` 参数恢复旧的行为。例如：

  ```
  Book.objects.iterator(chunk_size=100)
  ```
- 在 [`JavaScriptCatalog`](/zh-hans/4.2/topics/i18n/translation/#django.views.i18n.JavaScriptCatalog) 视图的 `packages` 参数中提供未知的包名称现在会引发 `ValueError`，而不是默默通过。
- 现在，默认的 `Model.__str__()` 方法中会显示模型实例的主键，例如 `Question object (1)`。
- 现在，`makemigrations` 会检测到模型字段的 `limit_choices_to` 选项的更改。请将其添加到现有的迁移中，或接受为使用它的字段生成的自动生成的迁移。
- 在 MySQL 上执行需要 [自动空间转换](/zh-hans/4.2/ref/contrib/gis/tutorial/#automatic-spatial-transformations) 的查询现在会引发 `NotImplementedError`，而不再默默地使用未经转换的几何图形。
- 移除了 `django.core.exceptions.DjangoRuntimeWarning`。它只在缓存后端中用作 `CacheKeyWarning` 继承 `RuntimeWarning` 的中间类。
- 将 `BaseExpression._output_field` 重命名为 `output_field`。您可能需要更新自定义表达式。
- 在旧版本中，表单和表单集通过连接两者的 `Media` 来合并小部件的 `Media`。现在，合并尝试 [保持每个列表中元素的相对顺序](/zh-hans/4.2/topics/forms/media/#form-media-asset-order)。如果无法保持顺序，将发出 `MediaOrderConflictWarning` 警告。
- 移除了 `django.contrib.gis.gdal.OGRException`。自 Django 1.8 起，它一直是 `GDALException` 的别名。
- 不再支持 GEOS 3.3.x 版本。
- 选择 `GeometryField` 的数据的方式已更改以提高性能，在原始 SQL 查询中，现在必须将这些字段包装在 `connection.ops.select` 中。请参阅 GIS 教程中的 [原始查询注意事项](/zh-hans/4.2/ref/contrib/gis/tutorial/#gis-raw-sql) 以获取示例。

## 在 2.0 中被废弃的功能

### `Field.from_db_value()` 和 `Expression.convert_value()` 的 `context` 参数

`Field.from_db_value()` 和 `Expression.convert_value()` 的 `context` 参数未被使用，因为它始终是一个空字典。现在这两个方法的签名是：

```
(self, value, expression, connection)
```

替换成：

```
(self, value, expression, connection, context)
```

对于自定义字段和表达式的旧签名，将继续支持直到 Django 3.0 版本。

### 杂项

- `django.db.backends.postgresql_psycopg2` 模块已被弃用，推荐使用 `django.db.backends.postgresql`。自 Django 1.9 起，它一直是一个别名。这仅影响直接从模块导入的代码。尽管如此，`DATABASES` 设置仍然可以使用 `'django.db.backends.postgresql_psycopg2'`，但您可以使用 Django 1.9 中添加的 `'django.db.backends.postgresql'` 名称来简化它。
- `django.shortcuts.render_to_response()` 已被弃用，推荐使用 [`django.shortcuts.render()`](/zh-hans/4.2/topics/http/shortcuts/#django.shortcuts.render)。`render()` 接受与之前相同的参数，只是现在需要传递一个 `request` 参数。
- `DEFAULT_CONTENT_TYPE` 设置已被弃用。它与第三方应用程序的兼容性不佳，并且自 HTML5 大多代替了 XHTML 后已过时。
- `HttpRequest.xreadlines()` 已被弃用，建议改为迭代请求对象。
- [`QuerySet.earliest()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.earliest) 和 [`QuerySet.latest()`](/zh-hans/4.2/ref/models/querysets/#django.db.models.query.QuerySet.latest) 中的 `field_name` 关键字参数已被弃用，推荐将字段名称作为参数传递。请使用 `.earliest('pub_date')` 而不是 `.earliest(field_name='pub_date')`。

## 在 2.0 版本中移除的功能

这些功能已经完成了废弃周期，并在 Django 2.0 中被移除。

有关这些更改的详细信息，包括如何删除对这些特性的使用，请参阅 [在 1.9 中被废弃的功能](/zh-hans/4.2/releases/1.9/#deprecated-features-1-9)。

- `django.dispatch.signals.Signal.disconnect()` 中的 `weak` 参数已被移除。
- `django.db.backends.base.BaseDatabaseOperations.check_aggregate_support()` 已被移除。
- `django.forms.extras` 包已被移除。
- `assignment_tag` 辅助函数已被移除。
- `SimpleTestCase.assertsRedirects()` 中的 `host` 参数已被移除。兼容性层也被移除，该层允许在路径相同时将绝对 URL 视为与相对 URL 相等。
- `Field.rel` 和 `Field.remote_field.to` 已被移除。
- 在模型和迁移中，`ForeignKey` 和 `OneToOneField` 的 `on_delete` 参数现在是必需的。考虑合并迁移以减少需要更新的迁移数量。
- 移除了 `django.db.models.fields.add_lazy_relation()`。
- 启用时间区域支持时，不再在数据库后端不支持时间区域的情况下将感知的日期时间转换为 UTC 中的非感知值，当这样的值作为参数传递给 ORM 之外的 SQL 查询执行时（例如使用 `cursor.execute()`）。
- `django.contrib.auth.tests.utils.skipIfCustomUser()` 已被移除。
- `GeoManager` 和 `GeoQuerySet` 类已被移除。
- `django.contrib.gis.geoip` 模块已被移除。
- 模板加载器的 `supports_recursion` 检查已从以下地方移除：

  - `django.template.engine.Engine.find_template()`
  - `django.template.loader_tags.ExtendsNode.find_template()`
  - `django.template.loaders.base.Loader.supports_recursion()`
  - `django.template.loaders.cached.Loader.supports_recursion()`
- 已移除 `load_template` 和 `load_template_sources` 模板加载器方法。
- 模板加载器的 `template_dirs` 参数已被移除：

  - `django.template.loaders.base.Loader.get_template()`
  - `django.template.loaders.cached.Loader.cache_key()`
  - `django.template.loaders.cached.Loader.get_template()`
  - `django.template.loaders.cached.Loader.get_template_sources()`
  - `django.template.loaders.filesystem.Loader.get_template_sources()`
- `django.template.loaders.base.Loader.__call__()` 已被移除。
- 不接受 `exception` 参数的自定义错误视图的支持已被移除。
- `django.utils.feedgenerator.Atom1Feed` 和 `django.utils.feedgenerator.RssFeed` 的 `mime_type` 属性已被移除。
- `include()` 中的 `app_name` 参数已被移除。
- 不再支持将一个包含 `admin.site.urls` 的 3 元组作为 `include()` 的第一个参数。
- 不再支持在没有应用程序命名空间的情况下设置 URL 实例命名空间。
- `Field._get_val_from_obj()` 已被移除。
- 移除了 `django.template.loaders.eggs.Loader`。
- `contrib.auth` 函数式视图的 `current_app` 参数已被移除。
- `SimpleTestCase.assertRaisesMessage()` 中的 `callable_obj` 关键字参数已被移除。
- 不再支持在 `ModelAdmin` 方法上的 `allow_tags` 属性。
- `SyndicationFeed.add_item()` 中的 `enclosure` 关键字参数已被移除。
- `django.template.loader.LoaderOrigin` 和 `django.template.base.StringOrigin` 别名已被移除，对应的是 `django.template.base.Origin`。

请参阅 [在 1.10 中被废弃的功能](/zh-hans/4.2/releases/1.10/#deprecated-features-1-10) 以获取有关这些更改的详细信息。

- `makemigrations --exit` 选项已被移除。
- 不再支持直接对反向外键或多对多关系进行赋值。
- `django.contrib.gis.geos.GEOSGeometry` 的 `get_srid()` 和 `set_srid()` 方法已被移除。
- `django.contrib.gis.geos.Point` 的 `get_x()`, `set_x()`, `get_y()`, `set_y()`, `get_z()`, 和 `set_z()` 方法已被移除。
- `django.contrib.gis.geos.Point` 的 `get_coords()` 和 `set_coords()` 方法已被移除。
- `django.contrib.gis.geos.MultiPolygon` 的 `cascaded_union` 属性已被移除。
- `django.utils.functional.allow_lazy()` 已被移除。
- `shell --plain` 选项已被移除。
- `django.core.urlresolvers` 模块已被移除，现在请使用其新位置 `django.urls`。
- `CommaSeparatedIntegerField` 已被移除，除了对历史迁移的支持外。
- 模板 `Context.has_key()` 方法已被移除。
- 对于 `django.core.files.storage.Storage.accessed_time()`, `created_time()` 和 `modified_time()` 方法的支持已被移除。
- 当设置了 `Meta.default_related_name` 时，不再支持使用模型名称进行查询查找。
- MySQL 中的 `__search` 查找已被移除。
- 移除了支持自定义相关管理器类但没有 `_apply_rel_filters()` 方法的 shim。
- 不再支持将 `User.is_authenticated()` 和 `User.is_anonymous()` 作为方法使用，而不是属性。
- `Model._meta.virtual_fields` 属性已被移除。
- `Field.contribute_to_class()` 中的关键字参数 `virtual_only` 和 `Model._meta.add_field()` 中的 `virtual` 已被移除。
- `javascript_catalog()` 和 `json_catalog()` 视图已被移除。
- `django.contrib.gis.utils.precision_wkt()` 已被移除。
- 在多表继承中，不再隐式将 `OneToOneField` 提升为 `parent_link`。
- 不再支持 `Widget._format_value()`。
- `FileField` 的方法 `get_directory_name()` 和 `get_filename()` 已被移除。
- `mark_for_escaping()` 函数以及它使用的类：`EscapeData`、`EscapeBytes`、`EscapeText`、`EscapeString` 和 `EscapeUnicode` 都已被移除。
- `escape` 过滤器现在使用 `django.utils.html.conditional_escape()`。
- `Manager.use_for_related_fields` 已被移除。
- 模型的 `Manager` 继承遵循 MRO 继承规则。不再需要使用 `Meta.manager_inheritance_from_future` 来选择使用这种行为。
- 不再支持使用 `settings.MIDDLEWARE_CLASSES` 的老式中间件。
