- Django 1.9 版本发行说明
- Python 兼容性
- Django 1.9 的新特性
- 1.9 版本中的不向后兼容变更
- 数据库后端 API
- 原来的默认设置是元组,现在改为列表
- 模板加载器上的
is_usable
属性已被移除。 - 相关集合直接赋值
- 基于文件系统的模板加载器捕获更具体的异常
- HTTP 重定向不再强制要求使用绝对 URI
- 不再支持 PostgreSQL 9.0 版本
- 不再支持 Oracle 11.1 版本
- 关于相关管理器的
add()
方法的批量行为 - 模板中移除了
LoaderOrigin
和StringOrigin
- 默认日志配置的更改
- 在错误报告中的
HttpRequest
详细信息 - 移除了日期时间的时区感知全局适配器和转换器
- 在配置模板时导入模板标签模块
- 已删除
django.template.base.add_to_builtins()
。 simple_tag
现在在标签输出中包装了conditional_escape
Paginator.page_range
- 隐式的
QuerySet
__in
查询已移除 contrib.admin
浏览器支持- 在
setuptools
5.5.x 安装 Django 时出现SyntaxError
错误 - 杂项
- 在 1.9 中被废弃的功能
- 在 1.9 版本中移除的功能。
Django 1.9 版本发行说明
2015 年 12 月 1 日
欢迎使用 Django 1.9 !
这些发布说明包括 新特性,以及从 Django 1.8 或更早版本升级时需要注意的一些 不兼容变更。我们已经 删除了一些已经完成了其废弃周期的功能,并且已经 开始废弃某些功能。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Python 兼容性
Django 1.9 需要 Python 2.7、3.4 或 3.5。我们 强烈建议 并且只官方支持每个系列的最新版本。
Django 1.8 系列是最后一个支持 Python 3.2 和 3.3 的版本。
Django 1.9 的新特性
事务提交后执行操作
新的 on_commit() 钩子允许在数据库事务成功提交后执行操作。这对于执行诸如发送通知电子邮件、创建排队任务或使缓存无效等任务非常有用。
这个功能已经被集成到 Django 中,之前是作为 django-transaction-hooks 包的一部分。
密码验证
Django 现在提供密码验证功能,以帮助防止用户使用弱密码。该验证已集成在包含的密码更改和重置表单中,并且可以简单地集成到任何其他代码中。验证由一个或多个验证器执行,可以在新的 AUTH_PASSWORD_VALIDATORS 设置中配置。
Django 中包含了四个验证器,可以强制实施最小长度、将密码与用户的属性进行比较(如姓名)、确保密码不全为数字,或者检查是否在包含的常见密码列表中。您可以组合多个验证器,并且某些验证器具有自定义配置选项。例如,您可以选择提供自定义的常见密码列表。每个验证器都提供帮助文本,向用户解释其要求。
默认情况下,不执行任何验证,所有密码都会被接受,因此如果您不设置 AUTH_PASSWORD_VALIDATORS,您将不会看到任何更改。在使用默认 startproject 模板创建的新项目中,已启用一组简单的验证器。要在您的项目中为包含的认证表单启用基本验证,您可以设置如下配置,例如:
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
有关更多详细信息,请参阅 密码验证。
用于基于类的视图的权限混合类
Django 现在包含了一些 mixin 类,如 AccessMixin、LoginRequiredMixin、PermissionRequiredMixin 和 UserPassesTestMixin,用于为基于类的视图提供与 django.contrib.auth.decorators
相同的功能。这些 mixin 类来自或受到了 django-braces 项目的启发。
尽管如此,在 Django 和 django-braces
‘ 的实现之间存在一些差异:
- raise_exception 属性只能为
True
或False
。不支持自定义异常或可调用对象。 - handle_no_permission() 方法不接受
request
参数。当前请求可在self.request
中获取。 - UserPassesTestMixin 的自定义
test_func()
不接受user
参数。当前用户可在self.request.user
中获取。 - permission_required 属性支持一个字符串(定义一个权限)或一个字符串的列表/元组(定义多个权限),这些权限需要满足才能授予访问权限。
- 新的 permission_denied_message 属性允许传递消息给
PermissionDenied
异常。
contrib.admin
中的新样式
管理员界面采用了现代的扁平设计,使用新的 SVG 图标,在高分辨率屏幕上效果非常好。它仍然在 YUI’s A-grade 浏览器中提供了完全功能的体验。较旧的浏览器可能会有不同程度的优雅降级。
并行运行测试
test 命令现在支持 --parallel 选项,可以并行运行项目的测试,使用多个进程。
每个进程都会得到它们自己的数据库。你必须确保不同的测试用例不会访问相同的资源。例如,接触文件系统的测试用例应该创建一个临时目录供自己使用。
对于 Django 自身的测试套件,默认情况下启用了此选项。
- 只要操作系统支持(除了 Windows),此选项就会默认启用。
- 只要数据库后端支持(除了 Oracle),此选项就会默认启用。
次要特性
django.contrib.admin
- 管理员视图现在具有
model_admin
或admin_site
属性。 - 管理员更改视图的 URL 已更改(默认情况下是
/admin/<app>/<model>/<pk>/
,现在是/admin/<app>/<model>/<pk>/change/
)。这不会影响您的应用程序,除非您已经硬编码了管理员的 URL。在这种情况下,建议使用 反向管理员 URL 来替代这些链接。请注意,旧的 URL 仍然会重定向到新的 URL 以保持向后兼容,但它可能在将来的版本中被删除。 - 添加了 ModelAdmin.get_list_select_related() 方法,允许根据请求更改管理员的变更列表查询中使用的
select_related()
值。 - 已将
available_apps
上下文变量添加到 AdminSite.each_context() 方法中,该变量列出了当前用户可用的应用程序。 - 添加了 AdminSite.empty_value_display 和 ModelAdmin.empty_value_display,用于覆盖管理员更改列表中空值的显示。您还可以为每个字段自定义该值。
- 在更改表单页面上添加了 jQuery 事件,用于 在添加或删除内联表单时。
- 时间选择器小部件包括一个“下午 6 点”的选项,以保持每 6 小时预定义选项的一致性。
- 现在,JavaScript 的 slug 生成支持罗马尼亚字符。
django.contrib.admindocs
admindocs
的模型部分现在还描述了接受参数的方法,而不是忽略它们。
django.contrib.auth
- PBKDF2 密码哈希器的默认迭代次数增加了 20%。这个向后兼容的更改不会影响那些已经子类化了
django.contrib.auth.hashers.PBKDF2PasswordHasher
来更改默认值的用户。 - 如果更改了
BCryptSHA256PasswordHasher
的rounds
属性,它将更新密码。 AbstractBaseUser
和BaseUserManager
被移动到了新的django.contrib.auth.base_user
模块,因此可以在不包括django.contrib.auth
在 INSTALLED_APPS 中的情况下导入它们(在较旧的版本中,这样做会引发废弃警告,在 Django 1.9 中不再支持)。- permission_required() 的权限参数接受所有类型的可迭代对象,而不仅仅是列表和元组。
- 新的 PersistentRemoteUserMiddleware 使得在仅在登录页面上填充标头的设置中使用
REMOTE_USER
成为可能,而不是在会话的每个请求中都填充。 django.contrib.auth.views.password_reset()
视图接受一个extra_email_context
参数。
django.contrib.contenttypes
- 现在可以在
GenericForeignKey
中使用 order_with_respect_to。
django.contrib.gis
- 所有
GeoQuerySet
方法都已被废弃,并被 等效的数据库函数 替代。一旦在您的代码中替换了这些旧方法,您甚至可以从启用 GIS 的类中删除特殊的GeoManager
。 - GDAL 接口现在支持从原始数据实例化基于文件和内存的 GDALRaster 对象。已添加了用于栅格属性(如投影或像素值)的设置器。
- 对于 PostGIS 用户,新的 RasterField 允许 存储 GDALRaster 对象。它支持在保存模型时自动创建空间索引和重投影。但它目前还不支持空间查询。
- 新的 GDALRaster.warp() 方法允许通过指定目标栅格属性(如原点、宽度、高度或像素大小等)来进行栅格重投影。
- 新的 GDALRaster.transform() 方法允许通过指定目标
srid
来将栅格转换为不同的空间参考系统。 - 新的 GeoIP2 类允许使用 MaxMind 的 GeoLite2 数据库,其中包括对 IPv6 地址的支持。
- 包含在小部件中的默认 OpenLayers 库版本已从 2.13 更新为 2.13.1 。
django.contrib.postgres
- 为一些内置字段添加了对 rangefield.contained_by 查找的支持,这些字段对应于范围字段。
- 添加了
django.contrib.postgres.fields.JSONField
。 - 添加了 PostgreSQL 特有聚合函数。
- 添加了 TransactionNow 数据库函数。
django.contrib.sessions
- 会话模型和用于
db
和cached_db
后端的SessionStore
类已进行了重构,以允许自定义数据库会话后端基于它们构建。有关更多详细信息,请参阅 扩展数据库后端的会话引擎。
django.contrib.sites
- get_current_site() 现在处理了
request.get_host()
返回domain:port
的情况,例如example.com:80
。如果查找失败,因为主机在数据库中找不到记录并且主机有一个端口,端口会被剥离,然后使用仅包含域名的部分重试查找。
django.contrib.syndication
- 添加了对每个订阅项多个附件的支持。如果在 RSS 订阅中定义了多个附件,则会引发异常,因为 RSS 订阅不支持每个订阅项多个附件,而 Atom 订阅支持。
缓存
django.core.cache.backends.base.BaseCache
现在具有一个get_or_set()
方法。- django.views.decorators.cache.never_cache() 现在发送更具说服力的头部信息(在
Cache-Control
中添加了no-cache, no-store, must-revalidate
),以更好地防止缓存。这也在 Django 1.8.8 中添加了。
CSRF
- 用于 CSRF 认证的请求头名称可以通过 CSRF_HEADER_NAME 进行自定义。
- 如果设置了 CSRF_COOKIE_DOMAIN 设置,CSRF 的 referer 头现在将与其进行验证。有关详细信息,请参阅 工作方式。
- 新的 CSRF_TRUSTED_ORIGINS 设置提供了一种允许跨源不安全请求(例如
POST
)通过 HTTPS 的方式。
数据库后端
- PostgreSQL 后端(
django.db.backends.postgresql_psycopg2
)也可以使用django.db.backends.postgresql
。旧名称将继续保持以确保向后兼容。
文件存储
- 当 upload_to 是可调用对象时,现在会调用 Storage.get_valid_name()。
- 在使用 Python 3 时,File 现在具有
seekable()
方法。
表单
- ModelForm 接受新的
Meta
选项field_classes
以自定义字段的类型。有关详细信息,请参阅 覆盖默认字段。 - 现在可以使用 field_order 属性、
field_order
构造函数参数或 order_fields() 方法指定表单字段呈现的顺序。 - 现在可以在表单类内部指定表单前缀,而不仅仅是在实例化表单时。有关详细信息,请参阅 表单前缀。
- 现在可以 指定要传递给表单集合中表单构造函数的关键字参数。
- SlugField 现在接受一个 allow_unicode 参数,以允许在 slug 中使用 Unicode 字符。
- CharField 现在接受一个 strip 参数,以去除输入数据的前导和尾随空格。由于默认为
True
,这与之前的版本不同。 - 现在,表单字段支持 disabled 参数,允许浏览器将字段小部件显示为禁用状态。
- 现在可以通过重写字段的 get_bound_field() 方法来自定义绑定字段。
通用视图
- 使用
as_view()
生成的基于类的视图现在具有view_class
和view_initkwargs
属性。 - 现在可以使用 method_decorator() 与装饰器的列表或元组一起使用。它还可以用于 装饰类而不是方法。
国际化
- 当可用时,django.views.i18n.set_language() 视图现在正确重定向到 已翻译的 URL。
- 如果在同一页上多次使用不同配置调用
django.views.i18n.javascript_catalog()
视图,它现在会正常工作。 - django.utils.timezone.make_aware() 函数新增了一个
is_dst
参数,以帮助解决夏令时转换期间的模糊时间。 - 现在可以使用 gettext 支持的语言区域变体。这通常用于可以使用不同字符集书写的语言,例如拉丁文和西里尔文(例如
be@latin
)。 - 新增了
django.views.i18n.json_catalog()
视图,以帮助构建基于 Django 翻译的自定义客户端端国际化库。它返回一个包含翻译目录、格式设置和复数规则的 JSON 对象。 - 新增了 get_language_info 模板标签返回的对象的
name_translated
属性。还新增了相应的模板过滤器:language_name_translated。 - 现在你可以从项目的根目录运行 compilemessages,它将找到所有由 makemessages 创建的应用程序消息文件。
- 现在 makemessages 每个区域目录调用一次
xgettext
而不是每个可翻译文件调用一次。这加快了本地化构建的速度。 - blocktrans 支持使用
asvar
将其输出分配给变量。 - 新增了两种新语言:哥伦比亚西班牙语和苏格兰盖尔语。
管理命令
- 新的 sendtestemail 命令允许您发送测试邮件,以轻松确认通过 Django 发送邮件是否正常工作。
- 为了增加 sqlmigrate 生成的 SQL 代码的可读性,为每个迁移操作生成的 SQL 代码前面都有操作的描述。
- dumpdata 命令的输出现在具有确定性的顺序。此外,当指定了
--output
选项时,它还在终端中显示一个进度条。 - createcachetable 命令现在有一个
--dry-run
标志,可以打印出 SQL 而不执行它。 - startapp 命令会创建一个
apps.py
文件。由于它不使用default_app_config
(一个不推荐使用的 API),你必须在 INSTALLED_APPS 中指定 app 配置的路径,例如'polls.apps.PollsConfig'
,以便使用它(而不仅仅是'polls'
)。 - 在使用 PostgreSQL 后端时,dbshell 命令可以使用设置文件中的密码来连接数据库(而不需要手动输入密码)。
django
包可以作为脚本运行,即python -m django
,它的行为与django-admin
相同。- 具有
--noinput
选项的管理命令现在还支持--no-input
作为该选项的别名。
迁移
初始迁移现在带有一个 initial = True 类属性,这允许 migrate —fake-initial 更容易检测到初始迁移。
增加了对
functools.partial
和LazyObject
实例的序列化支持。当在 MIGRATION_MODULES 中提供
None
作为值时,Django 将考虑该应用程序为没有迁移的应用程序。在应用迁移时,当以 verbosity 2 或更高级别运行 migrate 命令时,” Rendering model states “ 步骤现在仅计算已应用的迁移的模型状态。正在应用的迁移的模型状态将按需生成,大大减少了所需的内存。
然而,这个改进在取消应用迁移时不适用,因此仍然需要预先计算和存储中间迁移状态。
这个改进还要求 Django 不再支持混合迁移计划。混合计划包含一系列迁移,其中一些正在应用,而其他一些正在取消应用。这从未得到官方支持,并且从未有过公共 API 来支持这种行为。
squashmigrations 命令现在支持指定要压缩的迁移的起始迁移。
模型
- QuerySet.bulk_create() 现在可以在代理模型上使用。
- 数据库配置增加了一个 TIME_ZONE 选项,用于与在 USE_TZ 为
True
时不支持时区的数据库交互,这些数据库将日期时间存储在本地时间中。 - 新增了 RelatedManager.set() 方法,用于与由
ForeignKey
、GenericForeignKey
和ManyToManyField
创建的相关管理器交互。 - add() 方法在反向外键上现在有一个
bulk
参数,允许执行一个查询,而不管要添加的对象数量如何,而不是每个对象执行一个查询。 - 在 Model.delete() 方法中添加了
keep_parents
参数,允许仅删除使用多表继承的模型中子模型的数据。 - Model.delete() 和 QuerySet.delete() 返回被删除的对象数量。
- 添加了一个系统检查,防止在同一模型上同时定义
Meta.ordering
和order_with_respect_to
。 - 日期和时间 查询可以与其他查询(如 exact, gt, lt 等)链接使用。例如:
Entry.objects.filter(pub_date__month__gt=6)
。 - 时间查询(小时,分钟,秒)现在对所有数据库后端都受到 TimeField 的支持。在 Django 1.7 中添加了对除 SQLite 外的后端的支持,但未记录在文档中。
- 你可以通过指定 Avg 聚合的
output_field
参数来对非数字列(如DurationField
)进行聚合。 - 在 DateTimeField 中添加了 date 查询,允许仅查询字段的日期部分。
- 添加了 Greatest 和 Least 数据库函数。
- 添加了 Now 数据库函数,该函数返回当前的日期和时间。
- Transform 现在是 Func() 的子类,这使得
Transform
可以像常规的Func
一样用在表达式的右侧。这允许注册一些数据库函数,如 Length、Lower 和 Upper 作为转换函数。 - SlugField 现在接受一个 allow_unicode 参数,允许在 slug 中使用 Unicode 字符。
- 在
QuerySet.distinct()
中增加了对注解引用的支持。 connection.queries
在 SQLite 上显示带有替代参数的查询。- 查询表达式 现在可以在使用
save()
,create()
和bulk_create()
创建新模型实例时使用。
请求和响应
- 除非显式设置 HttpResponse.reason_phrase,否则它现在由 HttpResponse.status_code 的当前值确定。在构造函数之外修改
status_code
的值也会修改reason_phrase
的值。 - 调试视图现在在 Python 3 上显示链式异常的详细信息。
- 默认的 40x 错误视图现在接受第二个位置参数,即触发视图的异常。
- 视图错误处理程序现在支持 TemplateResponse,这在使用基于类的视图时常常使用。
- 由
render()
方法引发的异常现在会传递给每个中间件的process_exception()
方法。 - 请求中间件现在可以将 HttpRequest.urlconf 设置为
None
,以撤销之前中间件所做的任何更改并返回使用 ROOT_URLCONF。 - 在 CommonMiddleware 中的 DISALLOWED_USER_AGENTS 检查现在引发 PermissionDenied 异常,而不是返回 HttpResponseForbidden,以便调用 handler403。
- 添加了 HttpRequest.get_port() 方法,用于获取请求的起始端口。
- 在 JsonResponse 中添加了
json_dumps_params
参数,允许将关键字参数传递给用于生成响应的json.dumps()
调用。 - BrokenLinkEmailsMiddleware 现在在引用者等于请求的 URL 时忽略 404 错误。为了规避已经实施的空引用检查,一些网络爬虫将引用者设置为请求的 URL。
模板
- 使用 simple_tag() 辅助程序创建的模板标签现在可以使用
as
参数将结果存储在模板变量中。 - 添加了 Context.setdefault() 方法。
- 添加了 django.template 记录器,并包括以下消息:
- 对于缺少上下文变量的情况,添加了一个
DEBUG
级别的消息。 - 在关闭调试模式时,对于在渲染
{% include %}
期间引发的未捕获异常,添加了一个WARNING
级别的消息(这对于{% include %}
会将异常消除并返回空字符串的情况很有帮助)。
- 对于缺少上下文变量的情况,添加了一个
- firstof 模板标签支持使用 ‘as’ 将输出存储在一个变量中。
- Context.update() can now be used as a context manager.
- Django 模板加载器现在可以递归地扩展模板。
- 调试页面模板的事后分析现在包括安装的每个引擎的输出。
- 为自定义模板引擎添加了 调试页面集成。
- DjangoTemplates 后端通过模板 OPTIONS 获得了明确注册库和内置函数的能力。
timesince
和timeuntil
过滤器在处理大时间跨度时进行了改进,以应对闰年。include
标签现在在模板渲染期间缓存解析的模板对象,加快了在诸如 for 循环等地方的重复使用。
测试
- 在测试客户端响应中添加了 json() 方法,以便访问响应体作为 JSON。
- 在测试客户端中添加了 force_login() 方法。使用该方法模拟用户登录站点的效果,同时跳过 login() 的身份验证和验证步骤。
URLs
- URL 模式中现在允许使用正则表达式的环视断言。
- 应用程序命名空间现在可以通过在包含的模块或对象上设置
app_name
属性来设置。也可以通过将一个 2 元组(<模式列表>,<应用程序命名空间>)作为include()
的第一个参数来设置。 - 已添加了用于检测常见 URL 模式错误的系统检查。
验证器
- 添加了 django.core.validators.int_list_validator(),用于生成验证包含整数并用自定义字符分隔的字符串的验证器。
- EmailValidator 现在根据 RFC 1034,限制了域名标签的长度为 63 个字符。
- 添加了 validate_unicode_slug(),用于验证可能包含 Unicode 字符的 slugs。
1.9 版本中的不向后兼容变更
警告
除了本节中概述的更改之外,请确保查看 在 1.9 版本中移除的功能。,了解已经完成弃用周期并因此被移除的功能。如果您没有在给定功能的弃用时间内更新您的代码,其移除可能会被视为不兼容的更改。
数据库后端 API
一些新的测试依赖于后端能够自省列的默认值(将结果返回为
Field.default
)。如果您的后端没有实现这个功能,您可以将数据库特性can_introspect_default
设置为False
。您可能希望参考 Django 包含的后端的实现来进行审查(#24245)。不鼓励在 DB-API 模块级别注册全局适配器或转换器来处理作为查询参数传递或作为查询结果返回的不支持时区的 datetime 值的时区信息。这可能会与其他库发生冲突。
向从数据库获取的 datetime 值添加时区的推荐方法是在
DatabaseOperations.get_db_converters()
中为DateTimeField
注册一个转换器。已移除了
needs_datetime_string_cast
数据库特性。设置了这个特性的数据库后端必须按照上述说明注册一个转换器。DatabaseOperations.value_to_db_<type>()
方法被重命名为adapt_<type>field_value()
,以与convert_<type>field_value()
方法保持一致。要使用新的
date
查询,第三方数据库后端可能需要实现DatabaseOperations.datetime_cast_date_sql()
方法。添加了
DatabaseOperations.time_extract_sql()
方法。它调用现有的date_extract_sql()
方法。SQLite 后端会重写此方法,以向 TimeField 添加时间查询(小时、分钟、秒),第三方数据库后端可能需要实现此方法。已删除
DatabaseOperations.datetime_cast_sql()
方法(请不要与上面提到的DatabaseOperations.datetime_cast_date_sql()
混淆)。这个方法在很多年前用于在 Oracle 上格式化日期,但很多年来没有被任何核心后端重写,也没有在 Django 代码或测试中被调用过。为了支持测试并行化,您必须实现
DatabaseCreation._clone_test_db()
方法并设置DatabaseFeatures.can_clone_databases = True
。您可能需要调整DatabaseCreation.get_test_db_clone_settings()
。
原来的默认设置是元组,现在改为列表
在 django.conf.global_settings
中的默认设置原来是列表和元组的组合。以前是元组的所有设置现在都改为了列表。
模板加载器上的 is_usable
属性已被移除。
以前,Django 模板加载器需要定义一个 is_usable
属性。如果在模板设置中配置了一个加载器并且该属性为 False
,则加载器将被静默忽略。在实际应用中,这只有 egg 加载器用于检测是否安装了 setuptools
。现在已删除 is_usable
属性,而 egg 加载器在运行时如果没有安装 setuptools
则会失败。
相关集合直接赋值
在 ORM 中直接分配相关对象以前会执行 clear()
,然后调用 add()
。这导致了不必要的大量数据更改,并且阻止使用 m2m_changed 信号来跟踪多对多关系中的个别更改。
直接赋值现在依赖于相关管理器上的新 set() 方法,默认情况下只处理现有相关集合与新分配的相关集合之间的更改。可以通过将直接赋值替换为带有关键字参数 clear=True
的 set()
调用来恢复先前的行为。
ModelForm
,因此 ModelAdmin
,在内部对于多对多关系依赖于直接赋值,并因此现在使用新行为。
基于文件系统的模板加载器捕获更具体的异常
使用 filesystem.Loader 或 app_directories.Loader 模板加载器时,较早版本的 Django 如果模板源存在但不可读,会引发 TemplateDoesNotExist 错误。这可能发生在许多情况下,例如如果 Django 没有权限打开文件,或者模板源是一个目录。现在,只有当模板源不存在时,Django 才会抑制异常。所有其他情况都会引发原始的 IOError
。
HTTP 重定向不再强制要求使用绝对 URI
相对重定向不再被转换为绝对 URI。RFC 2616 要求重定向响应中的 Location
标头必须是绝对 URI,但它已被 RFC 7231 取代,允许在 Location
中使用相对 URI,承认用户代理的实际实践,几乎所有用户代理都支持相对 URI。
因此,传递给 assertRedirects
的预期 URL 通常不再应包括 URL 的方案和域部分。例如,self.assertRedirects(response, 'http://testserver/some-url/')
应该替换为 self.assertRedirects(response, '/some-url/')
(除非重定向明确包含绝对 URL)。
在极少数情况下,如果您需要旧的行为(使用一个古老版本的 Apache 和 mod_scgi
发现将相对重定向解释为 “内部重定向” 的情况),您可以通过编写自定义中间件来恢复它:
class LocationHeaderFix(object):
def process_response(self, request, response):
if "Location" in response:
response["Location"] = request.build_absolute_uri(response["Location"])
return response
不再支持 PostgreSQL 9.0 版本
PostgreSQL 9.0 的上游支持于 2015 年 9 月结束。因此,Django 1.9 将 9.1 版本设定为其正式支持的最低 PostgreSQL 版本。
不再支持 Oracle 11.1 版本
Oracle 11.1 的上游支持于 2015 年 8 月结束。因此,Django 1.9 将 11.2 版本设定为其正式支持的最低 Oracle 版本。
关于相关管理器的 add()
方法的批量行为
为了提高性能,由 ForeignKey
和 GenericForeignKey
创建的相关管理器的 add()
方法从一系列 Model.save()
调用改为单个 QuerySet.update()
调用。这个变化意味着不再发送 pre_save
和 post_save
信号。您可以使用 bulk=False
关键字参数来恢复到以前的行为。
模板中移除了 LoaderOrigin
和 StringOrigin
在之前的 Django 版本中,当一个模板引擎以 True
的调试设置初始化时,一个 django.template.loader.LoaderOrigin
或 django.template.base.StringOrigin
的实例被设置为模板对象的 origin 属性。这些类已经合并为 Origin,并且无论引擎的调试设置如何,都会始终设置。为了最小程度的向后兼容性,旧的类名将保留为新的 Origin
类的别名,直到 Django 2.0。
默认日志配置的更改
为了更容易编写自定义的日志配置,Django 的默认日志配置不再定义 django.request
和 django.security
记录器。取而代之的是,它定义了一个名为 django
的记录器,过滤级别为 INFO
,具有两个处理程序:
console
:过滤级别为INFO
,仅在DEBUG=True
时激活。mail_admins
:过滤级别为ERROR
,仅在DEBUG=False
时激活。
如果您没有覆盖 Django 的默认日志配置,您的行为应该只会发生较少的变化,但您可能会在 runserver
控制台上看到一些新的日志记录,例如。
如果您正在覆盖 Django 的默认日志配置,您应该检查您的配置与新默认值如何合并。
在错误报告中的 HttpRequest
详细信息
每次在调试页面的 HTML 版本和错误邮件中作为堆栈帧变量出现时都显示完整的 HttpRequest 详细信息是多余的。因此,HTTP 请求现在将显示与其他变量相同的标准表示形式(repr(request)
)。因此,删除了 ExceptionReporterFilter.get_request_repr()
方法和未记录的 django.http.build_request_repr()
函数。
电子邮件的文本版本内容已修改,以提供与 AJAX 请求的情况相同结构的回溯。回溯详细信息由 ExceptionReporter.get_traceback_text()
方法呈现。
移除了日期时间的时区感知全局适配器和转换器
Django 不再注册全局适配器和转换器来管理发送到数据库的查询参数中的 datetime 值的时区信息,以及从查询结果中读取的时区信息。这个变化影响满足以下所有条件的项目:
- USE_TZ 设置为
True
。 - 数据库是 SQLite、MySQL、Oracle 或不支持时区的第三方数据库。如有疑问,您可以检查
connection.features.supports_timezones
的值。 - 代码在 ORM 之外查询数据库,通常使用
cursor.execute(sql, params)
。
如果您将感知的 datetime 参数传递给这些查询,您应该将它们转换为 UTC 中的非感知日期时间:
from django.utils import timezone
param = timezone.make_naive(param, timezone.utc)
如果您未这样做,转换将按照早期版本(带有弃用警告)中的方式执行,直到 Django 1.11 为止。 Django 2.0 不会执行任何转换,这可能导致数据损坏。
如果您从结果中读取 datetime 值,它们将是非感知的,而不是感知的。您可以按以下方式进行补偿:
from django.utils import timezone
value = timezone.make_aware(value, timezone.utc)
如果您通过 ORM 查询数据库,即使使用 raw() 查询,也不需要进行上述操作。ORM 会处理时区信息的管理。
在配置模板时导入模板标签模块
DjangoTemplates 后端现在在实例化时执行已安装的模板标签模块的发现。此更新使得在定义 DjangoTemplates 后端时,可以通过 OPTIONS 的 'libraries'
键明确提供库。模板标签模块中的导入或语法错误现在会在实例化时提前失败,而不是在首次编译带有 {% load %} 标签的模板时失败。
已删除 django.template.base.add_to_builtins()
。
虽然它是一个私有 API,但项目通常使用 add_to_builtins()
来使模板标签和过滤器在不使用 {% load %} 标签的情况下可用。这个 API 已经正式化。现在项目应该在定义 DjangoTemplates 后端时,通过 OPTIONS 的 'builtins'
键来定义内置库。
simple_tag
现在在标签输出中包装了 conditional_escape
通常,模板标签不会自动转义其内容,这种行为是被 文档记录的。对于像 inclusion_tag 这样的标签,这不是问题,因为被包含的模板会执行自动转义。对于 assignment_tag()
,当它在模板中作为变量使用时,输出会被转义。
然而,对于 simple_tag 的预期用例,很容易出现不正确的 HTML 和可能的 XSS 攻击。例如:
@register.simple_tag(takes_context=True)
def greeting(context):
return "Hello {0}!".format(context["request"].user.first_name)
在较早版本的 Django 中,这将是一个 XSS 问题,因为``user.first_name`` 没有经过转义。
在 Django 1.9 中,这个问题得到了修复:如果模板上下文设置了 autoescape=True
(默认值),那么 simple_tag
将使用 conditional_escape() 包装标签函数的输出。
要修复您的 simple_tag
,最好遵循以下实践:
- 生成 HTML 的任何代码都应该使用模板系统或 format_html()。
- 如果
simple_tag
的输出需要转义,请使用 escape() 或 conditional_escape()。 - 如果您绝对确定您正在输出来自可信源的 HTML(例如,由管理员输入的 HTML 存储在 CMS 字段中),您可以使用 mark_safe() 来标记它。
遵循这些规则的标签无论在 Django 1.9+ 还是之前的版本上运行,都将是正确和安全的。
Paginator.page_range
Paginator.page_range 现在是一个迭代器而不是一个列表。
在 Django 1.8 之前的版本中,Paginator.page_range
在 Python 2 中返回一个 list
,在 Python 3 中返回一个 range
。Django 1.8 一致返回一个列表,但迭代器更有效率。
依赖于 list
特定功能(如索引)的现有代码可以通过使用 list()
将迭代器转换为 list
来迁移。
隐式的 QuerySet
__in
查询已移除
在早期版本中,类似以下的查询:
Model.objects.filter(related_id=RelatedModel.objects.all())
会隐式转换为:
Model.objects.filter(related_id__in=RelatedModel.objects.all())
这将导致 SQL 查询类似于 "related_id IN (SELECT id FROM ...)"
。
这种隐式的 __in
不再发生,因此 “IN” SQL 现在变成了 “=”, 如果子查询返回多个结果,至少某些数据库会抛出错误。
contrib.admin
浏览器支持
管理员不再支持 Internet Explorer 8 及以下版本,因为这些浏览器已经到达生命周期终点。
已删除支持 Internet Explorer 6 和 7 的 CSS 和图像。 PNG 和 GIF 图标已被替换为 SVG 图标,这些图标不受 Internet Explorer 8 及更早版本的支持。
嵌入在管理员中的 jQuery 库已从 1.11.2 版本升级到 2.1.4 版本。 jQuery 2.x 具有与 jQuery 1.x 相同的 API,但不支持 Internet Explorer 6 、 7 或 8,从而实现更好的性能和更小的文件大小。如果您需要支持 IE8 并且必须使用最新版本的 Django,您可以通过创建具有以下结构的 Django 应用程序来覆盖管理员的 jQuery 副本:
app/static/admin/js/vendor/
jquery.js
jquery.min.js
在 setuptools
5.5.x 安装 Django 时出现 SyntaxError
错误
当使用 setuptools
5.5.x 安装 Django 1.9 或 1.9.1 时,你会看到:
Compiling django/conf/app_template/apps.py ...
File "django/conf/app_template/apps.py", line 4
class {{ camel_case_app_name }}Config(AppConfig):
^
SyntaxError: invalid syntax
Compiling django/conf/app_template/models.py ...
File "django/conf/app_template/models.py", line 1
{{ unicode_literals }}from django.db import models
^
SyntaxError: invalid syntax
你可以安全地忽略这些错误(Django 仍然会正常安装),但你可以通过升级 setuptools
到一个更近期的版本来避免它们。如果你使用 pip,你可以使用 python -m pip install -U pip
来升级 pip,这也会升级 setuptools
。这个问题在后续版本的 Django 中已经得到解决,如 Django 1.9.2 版本发行说明 中所描述的那样。
杂项
contrib.admin
中的 jQuery 静态文件已经移动到一个名为vendor/jquery
的子目录中。- 在管理 changelist 的
list_display
单元格中,空列的显示文本已经从(None)
(或其翻译等效)更改为-
(破折号)。 django.http.responses.REASON_PHRASES
和django.core.handlers.wsgi.STATUS_CODE_TEXT
已被移除。请改为使用 Python 标准库:对于 Python 3,使用 http.client.responses,对于 Python 2,使用 httplib.responses。ValuesQuerySet
和ValuesListQuerySet
已被移除。admin/base.html
模板不再设置window.__admin_media_prefix__
或window.__admin_utc_offset__
。在 JavaScript 中使用该值构建绝对 URL 的图像引用已经移动到 CSS 中,以便更容易进行自定义。UTC 偏移量存储在<body>
标签的数据属性中。CommaSeparatedIntegerField
的验证已经更加精细化,不再允许像','
、',1'
和'1,,2'
这样的值。- 表单的初始化已经从 ProcessFormView.get() 方法移动到新的 FormMixin.get_context_data() 方法。如果你曾经重写了
get_context_data()
方法而没有调用super()
,这可能会造成不兼容。 - 不再支持 PostGIS 1.5 版本。
django.contrib.sites.models.Site.domain
字段已更改为 unique。- 为了强制执行测试隔离,现在默认情况下在 SimpleTestCase 测试中不允许数据库查询。你可以通过在测试类上设置
allow_database_queries
类属性为True
来禁用这个行为。 ResolverMatch.app_name
已更改,现在在嵌套命名空间的情况下包含完整的命名空间路径。为了与ResolverMatch.namespace
保持一致,现在空值是一个空字符串而不是None
。- 为了增强安全性,会话密钥必须至少为 8 个字符。
- 已移除私有函数
django.utils.functional.total_ordering()
。它包含了对于早于 Python 2.7.3 版本中functools.total_ordering()
bug 的一个解决方法。 - XML 序列化(通过 dumpdata 或 syndication 框架)曾经会输出它接收到的任何字符。现在,如果要序列化的内容包含 XML 1.0 标准不允许的控制字符,序列化将会失败并引发 ValueError。
- 现在,默认情况下,CharField 会自动去除输入的前导和尾随空白。你可以通过将新的 strip 参数设置为
False
来禁用这个功能。 - 在翻译并使用两个或更多连续百分号的模板文本,例如
"%%"
,在运行makemessages
后可能会有一个新的msgid
(很可能翻译会被标记为模糊)。新的msgid
将被标记为"#, python-format"
。 - 如果既没有设置 request.current_app,也没有设置 Context.current_app,那么 url 模板标签现在将使用当前请求的命名空间。如果不想使用命名空间提示,请将
request.current_app
设置为None
。 - SILENCED_SYSTEM_CHECKS 设置现在会禁止所有级别的消息。以前,
ERROR
级别或更高级别的消息会打印到控制台。 FlatPage.enable_comments
字段已从FlatPageAdmin
中移除,因为它未被应用程序使用。如果你的项目或第三方应用程序使用它,请 创建一个自定义的 ModelAdmin 来将其添加回去。- setup_databases() 的返回值和 teardown_databases() 的第一个参数已经改变。它们以前是
(old_names, mirrors)
元组,现在它们只是第一个项目,即old_names
。 - 默认情况下,LiveServerTestCase 尝试在 8081-8179 范围内查找可用端口,而不仅仅是尝试端口 8081。
- 现在,对于 ModelAdmin 的系统检查会检查实例而不是类。
- 出于性能原因,已经移除了应用混合迁移计划的私有 API 。混合计划包括一系列迁移,其中一些正在应用,而其他一些正在取消应用。
- 位于
django.db.models.fields.related
(私有 API)中的相关模型对象描述符类已经从related
模块移动到related_descriptors
,并且被重命名如下:ReverseSingleRelatedObjectDescriptor
是ForwardManyToOneDescriptor
SingleRelatedObjectDescriptor
是ReverseOneToOneDescriptor
ForeignRelatedObjectsDescriptor
是ReverseManyToOneDescriptor
ManyRelatedObjectsDescriptor
是ManyToManyDescriptor
- 如果你实现了自定义的 handler404 视图,它必须返回一个带有 HTTP 404 状态代码的响应。使用 HttpResponseNotFound 或将
status=404
传递给 HttpResponse。否则,在DEBUG=False
的情况下,APPEND_SLASH 不会正确工作。
在 1.9 中被废弃的功能
assignment_tag()
Django 1.4 版本添加了 assignment_tag
辅助函数,以简化在模板变量中存储结果的模板标签的创建。simple_tag() 辅助函数也具备了相同的功能,因此使得 assignment_tag
已经过时。使用 assignment_tag
的标签应该更新为使用 simple_tag
。
{% cycle %}
语法可以接受逗号分隔的参数
cycle 标签支持来自先前 Django 版本的旧语法:
{% cycle row1,row2,row3 %}
使用旧语法会导致解析错误,因此在加速弃用后,将在 Django 1.10 中删除对旧语法的支持。
ForeignKey
和 OneToOneField
的 on_delete
参数
为了增加对级联模型删除的认知,在 Django 2.0 中将要求在 ForeignKey
和 OneToOneField
中使用 on_delete
参数。
更新模型和现有的迁移以显式设置参数。由于默认值是 models.CASCADE
,因此请在所有不使用不同选项的 ForeignKey
和 OneToOneField
上添加 on_delete=models.CASCADE
。如果不关心与较早版本的 Django 的兼容性,也可以将其作为第二个位置参数传递。
Field.rel
变更
Field.rel
及其方法和属性已更改以匹配相关字段的 API。Field.rel
属性被重命名为 remote_field
,许多其方法和属性要么更改,要么重命名。
这些更改的目的是为关系字段提供一个有文档记录的 API 。
GeoManager
和 GeoQuerySet
的自定义方法
所有自定义的 GeoQuerySet
方法(如 area()
、distance()
、gml()
等)都已被等效的地理表达式注释所取代(请参见新特性)。因此,现在已经不再需要为支持 GIS 的模型设置自定义的 GeoManager
。一旦你的代码不再调用任何已弃用的方法,你可以简单地从模型中删除 objects = GeoManager()
行。
模板加载器的 API 已经改变。
Django 模板加载器已更新,允许递归模板扩展。这个变化需要一个新的模板加载器 API。旧的 load_template()
和 load_template_sources()
方法现在已被弃用。关于新 API 的详细信息可以在 模板加载器文档中 找到。
将一个 3 元组或一个 app_name
传递给 include()
传递元组作为参数到 include()
的实例命名空间部分已被替换为通过 include()
传递 namespace
参数。例如:
polls_patterns = [
url(...),
]
urlpatterns = [
url(r"^polls/", include((polls_patterns, "polls", "author-polls"))),
]
变成:
polls_patterns = (
[
url(...),
],
"polls",
) # 'polls' is the app_name
urlpatterns = [
url(r"^polls/", include(polls_patterns, namespace="author-polls")),
]
include()
中的 app_name
参数已被替换为传递一个 2 元组(如上所示),或者传递一个具有 app_name
属性的对象或模块(如下所示)。如果以这种新方式设置了 app_name
,那么 namespace
参数将不再需要。它将默认为 app_name
的值。例如,教程中的 URL 模式已更改为:
mysite/urls.py
urlpatterns = [url(r"^polls/", include("polls.urls", namespace="polls")), ...]
到:
mysite/urls.py
urlpatterns = [
url(r"^polls/", include("polls.urls")), # 'namespace="polls"' removed
...,
]
polls/urls.py
app_name = "polls" # added
urlpatterns = [...]
这个变化还意味着旧的包含 AdminSite
实例的方式已经被弃用。相反,直接将 admin.site.urls
传递给 django.conf.urls.url()
:
urls.py
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r"^admin/", admin.site.urls),
]
如果设置实例命名空间,需要提供 URL 应用程序命名空间。
在过去,没有应用程序命名空间的实例命名空间会起到与应用程序命名空间相同的作用,但如果存在相同名称的应用程序命名空间,无法对模式进行反向操作。指定实例命名空间的包含(includes)要求被包含的 URLconf 设置应用程序命名空间。
contrib.auth
视图的 current_app
参数
django.contrib.auth.views
中的所有视图都具有以下结构:
def view(request, ..., current_app=None, ...):
...
if current_app is not None:
request.current_app = current_app
return TemplateResponse(request, template_name, context)
从 Django 1.8 开始,current_app
已设置在 request
对象上。为了保持一致性,这些视图将要求调用者在 request
上设置 current_app
,而不是将其作为单独的参数传递。
django.contrib.gis.geoip
django.contrib.gis.geoip2 模块取代了 django.contrib.gis.geoip
。新模块提供了类似的 API,但不提供旧的 GeoIP-Python API 兼容方法。
杂项
django.dispatch.signals.Signal.disconnect()
中的weak
参数已被弃用,因为它没有效果。django.db.backends.base.BaseDatabaseOperations
的check_aggregate_support()
方法已被弃用,并将在 Django 2.0 中移除。应该改用更通用的check_expression_support()
。django.forms.extras
已被弃用。你可以在django.forms.widgets
(或简单地在django.forms
中)找到 SelectDateWidget。- 私有 API
django.db.models.fields.add_lazy_relation()
已被弃用。 django.contrib.auth.tests.utils.skipIfCustomUser()
装饰器已被弃用。随着 Django 1.6 中的测试发现变化,不再将django.contrib
应用程序的测试作为用户项目的一部分运行。因此,在django.contrib.auth
中不再需要使用@skipIfCustomUser
装饰器来装饰测试。- 如果你自定义了一些 错误处理程序,那些只有一个请求参数的视图签名已经被弃用。这些视图现在还应该接受一个名为
exception
的第二个位置参数。 django.utils.feedgenerator.Atom1Feed.mime_type
和django.utils.feedgenerator.RssFeed.mime_type
属性已被弃用,建议使用content_type
代替。- Signer 现在如果使用无效的分隔符会发出警告。这在 Django 1.10 中将变成异常。
django.db.models.Field._get_val_from_obj()
已被弃用,应使用Field.value_from_object()
。django.template.loaders.eggs.Loader
已被弃用,因为不建议将应用程序作为 eggs 分发。SimpleTestCase.assertRaisesMessage()
中的callable_obj
关键字参数已被弃用。请将可调用对象作为位置参数传递。- 在
ModelAdmin
方法中的allow_tags
属性已被弃用。在构建方法的返回值时,改用 format_html()、format_html_join() 或 mark_safe()。 SyndicationFeed.add_item()
中的enclosure
关键字参数已被弃用。改用新的enclosures
参数,它接受一个Enclosure
对象的列表,而不是单个对象。django.template.loader.LoaderOrigin
和django.template.base.StringOrigin
对于django.template.base.Origin
的别名已被弃用。
在 1.9 版本中移除的功能。
这些特性已经达到了它们的弃用周期的尽头,将在 Django 1.9 中被移除。详情请参见 在 1.7 中被废弃的功能,包括如何删除对这些特性的使用。
django.utils.dictconfig
已被移除。django.utils.importlib
已被移除。django.utils.tzinfo
已被移除。django.utils.unittest
已被移除。syncdb
命令已被移除。django.db.models.signals.pre_syncdb
和django.db.models.signals.post_syncdb
已被移除。- 数据库路由器上的
allow_syncdb
支持已被移除。 - 自动同步没有迁移的应用已被移除。对于所有应用程序,迁移是强制性的,除非你传递 migrate —run-syncdb 选项。
- 对于没有迁移的应用程序,已移除了 SQL 管理命令:
sql
、sqlall
、sqlclear
、sqldropindexes
和sqlindexes
。 - 已移除自动加载
initial_data
fixtures 和初始 SQL 数据的支持。 - 所有模型都需要在一个已安装的应用程序内定义,或者声明一个明确的 app_label。此外,在应用程序加载之前不能导入它们。特别是,在应用程序的根包内不能导入模型。
- 模型和表单的
IPAddressField
已被移除。为了与历史迁移兼容,仍然保留了一个存根字段。 - 不再支持
AppCommand.handle_app()
。 - 无法再从
django.contrib.sites.models
导入RequestSite
和get_current_site()
。 - 通过
runfcgi
管理命令的 FastCGI 支持已被移除。 django.utils.datastructures.SortedDict
已被移除。ModelAdmin.declared_fieldsets
已被移除。- 提供向后兼容性的
util
模块已被移除:django.contrib.admin.util
django.contrib.gis.db.backends.util
django.db.backends.util
django.forms.util
ModelAdmin.get_formsets
已被移除。- 用于将
BaseMemcachedCache._get_memcache_timeout()
方法重命名为get_backend_timeout()
的向后兼容 shims 已被移除。 - dumpdata 的
--natural
和-n
选项已被移除。 serializers.serialize()
的use_natural_keys
参数已被移除。- 私有 API
django.forms.forms.get_declared_fields()
已被移除。 - 使用
SplitDateTimeWidget
与DateTimeField
的能力已被移除。 WSGIRequest.REQUEST
属性已被移除。- 类
django.utils.datastructures.MergeDict
已被移除。 zh-cn
和zh-tw
语言代码已被移除。- 内部的
django.utils.functional.memoize()
已被移除。 django.core.cache.get_cache
已被移除。django.db.models.loading
已被移除。- 不再支持将可调用参数传递给查询集。
BaseCommand.requires_model_validation
被移除,取而代之的是requires_system_checks
。管理器验证器被管理器检查取代。ModelAdmin.validator_class
和default_validator_class
属性已被移除。ModelAdmin.validate()
已被移除。django.db.backends.DatabaseValidation.validate_field
被移除,取而代之的是check_field
方法。validate
管理命令已被移除。django.utils.module_loading.import_by_path
被移除,取而代之的是django.utils.module_loading.import_string
。ssi
和url
模板标签已从future
模板标签库中移除。django.utils.text.javascript_quote()
已被移除。- 不再支持将数据库测试设置作为独立的条目出现在数据库设置中,并以
TEST_
为前缀。 cache_choices
选项已被移除,不再适用于 ModelChoiceField 和 ModelMultipleChoiceField。RedirectView.permanent
属性的默认值已从True
更改为False
。django.contrib.sitemaps.FlatPageSitemap
已被移除,取而代之的是django.contrib.flatpages.sitemaps.FlatPageSitemap
。- 私有 API
django.test.utils.TestTemplateLoader
已被移除。 django.contrib.contenttypes.generic
模块已被移除。