2018 年 8 月 1 日
欢迎使用 Django 2.1 !
这些发布说明涵盖了 新功能,以及从 Django 2.0 或更早版本升级时需要注意的 不兼容变更。我们已经 删除了一些功能,这些功能已经到达了他们的弃用周期的末端,并且我们已经 开始了一些功能的弃用过程。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Django 2.1 支持 Python 3.5、3.6 和 3.7。Django 2.0 是最后一个支持 Python 3.4 的版本。我们 强烈推荐 并且只官方支持每个系列的最新发布版本。
模型的 Meta.default_permissions 属性中添加了 "view" 权限。这些新权限将在运行 migrate 时自动创建。
这允许将用户赋予对管理员中的模型的只读访问权限。新增了 ModelAdmin.has_view_permission()。该实现是向后兼容的,不需要分配 "view" 权限以允许拥有 "change" 权限的用户编辑对象。
有一些 不兼容考虑。
django.contrib.admin¶现在,ModelAdmin.search_fields 接受任何查找,如 field__exact。
jQuery 的版本已从 2.2.3 升级到 3.3.1 。
新的 ModelAdmin.delete_queryset() 方法允许自定义 "删除选定对象" 操作的删除过程。
现在你可以 覆盖默认的管理站点。
新的 ModelAdmin.sortable_by 属性和 ModelAdmin.get_sortable_by() 方法允许限制可以在更改列表页面中排序的列。
在 ModelAdmin.list_display 中的元素的 admin_order_field 属性现在可以是一个查询表达式。
新的 ModelAdmin.get_deleted_objects() 方法允许自定义删除视图和 "删除选定" 操作的删除过程。
actions.html、change_list_results.html、date_hierarchy.html、pagination.html、prepopulated_fields_js.html、search_form.html 和 submit_line.html 模板现在可以在每个应用程序或每个模型的基础上 被覆盖 (除了全局覆盖)。
管理员更改列表和更改表单对象工具现在可以在每个应用程序、每个模型或全局 被覆盖,使用 change_list_object_tools.html 和 change_form_object_tools.html 模板。
InlineModelAdmin.has_add_permission() 现在将父对象作为第二个位置参数传递,obj。
管理员操作现在可以 指定权限 以限制它们对某些用户的可用性。
django.contrib.auth¶createsuperuser 现在会提示是否允许绕过 AUTH_PASSWORD_VALIDATORS 检查。
django.contrib.gis¶新的 GEOSGeometry.buffer_with_style() 方法是 buffer() 的一个版本,允许自定义缓冲区的样式。
OpenLayersWidget 现在基于 OpenLayers 4.6.5(之前是 3.20.1)。
django.contrib.sessions¶添加了 SESSION_COOKIE_SAMESITE 设置,用于在会话 cookie 上设置 SameSite cookie 标志。
添加了 CSRF_COOKIE_SAMESITE 设置,用于在 CSRF cookie 上设置 SameSite cookie 标志。
ImageField 的小部件现在以带有 HTML 属性 accept="image/*" 渲染。
添加了 get_supported_language_variant() 函数。
领土语言变体的未翻译字符串现在使用通用语言的翻译。例如,未翻译的 pt_BR 字符串使用 pt 的翻译。
新的 inspectdb --include-views 选项允许为数据库视图创建模型。
BaseCommand 类现在使用自定义的帮助格式化程序,以使标准选项如 --verbosity 或 --settings 出现在帮助输出的最后,从而为子类命令的选项提供更突出的位置。
添加了对 functools.partialmethod 对象的序列化支持。
为了支持冻结的环境,迁移可以从 .pyc 文件中加载。
模型现在可以使用来自 PEP 487 的 __init_subclass__() 方法。
如果希望将它包含在模型表单中,可以将 BinaryField 设置为 editable=True。
新增了一些新的文本数据库函数:Chr、Left、LPad、LTrim、Ord、Repeat、Replace、Right、RPad、RTrim 和 Trim。
新的 TruncWeek 函数将 DateField 和 DateTimeField 截断到一周的星期一。
现在可以使用减号对查询表达式进行否定。
QuerySet.order_by() 和 distinct(*fields) 现在支持使用字段变换。
BooleanField 现在可以设置为 null=True。这是鼓励的,而不是使用 NullBooleanField,后者可能会在将来被弃用。
新的 QuerySet.explain() 方法显示查询集查询的数据库执行计划。
添加了 samesite 参数到 HttpResponse.set_cookie() 以允许设置 SameSite cookie 标志。
FileResponse 的新 as_attachment 参数设置了 Content-Disposition 头,使浏览器询问用户是否要下载文件。FileResponse 还会在适当的情况下尝试设置 Content-Type 和 Content-Length 头。
新的 json_script 过滤器安全地将 Python 对象输出为 JSON,包装在 <script> 标签中,可供 JavaScript 使用。
添加了对 307 和 308 重定向的测试支持,测试 Client。
测试 Client 现在如果 content_type='application/json',会将请求数据字典序列化为 JSON。你可以通过测试客户端的 json_encoder 参数自定义 JSON 编码器。
新的 SimpleTestCase.assertWarnsMessage() 方法是 assertWarnsRegex() 的简化版本。
本节介绍了第三方数据库后端可能需要的更改。
为了遵循 PEP 249,在数据库不支持某项功能时,异常已从 NotImplementedError 更改为 django.db.NotSupportedError。
将数据库特性标志 allow_sliced_subqueries 重命名为 allow_sliced_subqueries_with_in。
DatabaseOperations.distinct_sql() 现在需要额外的 params 参数,并返回一个包含 SQL 和参数的元组,而不是一个 SQL 字符串。
DatabaseFeatures.introspected_boolean_field_type 从方法更改为属性。
django.contrib.gis¶移除对 SpatiaLite 4.0 的支持。
MySQL 5.5 的上游支持结束于 2018 年 12 月。 Django 2.1 支持 MySQL 5.6 及更高版本。
PostgreSQL 9.3 的上游支持结束于 2018 年 9 月。 Django 2.1 支持 PostgreSQL 9.4 及更高版本。
PASSWORD_HASHERS 设置中移除了 BCryptPasswordHasher。¶如果你在 Django 1.4 或 1.5 中使用了 bcrypt(在 Django 1.6 中添加了 BCryptSHA256PasswordHasher),你可能有一些使用了 BCryptPasswordHasher 哈希算法的密码。
您可以像这样检查是否符合条件:
from django.contrib.auth import get_user_model
User = get_user_model()
User.objects.filter(password__startswith="bcrypt$$")
如果你想继续允许使用这些密码,你将需要定义 PASSWORD_HASHERS 设置(如果尚未定义),并包含 'django.contrib.auth.hashers.BCryptPasswordHasher'。
wrap_label 小部件模板上下文变量¶为了解决在使用 MultiWidget 时使用 RadioSelect 和 CheckboxSelectMultiple 时缺少 <label> 的问题,现在 wrap_label 上下文变量已经作为每个选项的属性出现。例如,在自定义的 input_option.html 模板中,将 {% if wrap_label %} 更改为 {% if widget.wrap_label %}。
新的 "view" 权限引入后,已存在的自定义管理员表单可能会在用户没有 "change" 权限时引发错误,因为表单可能会访问不存在的字段。通过覆盖 ModelAdmin.get_form() 方法,可以解决此问题,检查用户是否具有 "change" 权限,如果没有,则返回默认表单:
class MyAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if not self.has_change_permission(request, obj):
return super().get_form(request, obj, **kwargs)
return CustomForm
如果你有一个自定义权限,其代码名称的形式为 view_<modelname>,新的管理员中的视图权限处理将允许访问这些模型的 changelist 和详情页。如果这不是你想要的行为,你必须更改你的自定义权限代码名称。
mysqlclient 的最低支持版本已从 1.3.3 增加到 1.3.7。
不再支持 SQLite 版本低于 3.7.15 。
Set-Cookie 的 Expires 指令的日期格式已更改,以遵循 RFC 7231 Section 7.1.1.1,而不是 Netscape 的 cookie 标准。在日期中出现的连字符(如 Tue, 25-Dec-2018 22:26:13 GMT)已被移除。这个改变应该只是视觉上的变化,除非是一些不支持新格式的过时浏览器。
allowed_hosts 现在是私有 API django.utils.http.is_safe_url() 的必需参数。
SelectMultiple 小部件渲染的 multiple 属性现在使用 HTML5 的布尔语法,而不是 XHTML 的 multiple="multiple"。
由表单小部件渲染的 HTML 不再在空元素上包含闭合斜杠,例如 <br>。这在 XHTML 中不兼容,尽管一些小部件已经使用了 HTML5 的一些特性,如布尔属性。
SelectDateWidget 的空选项的值已从 0 更改为空字符串,这主要可能需要在比较 HTML 的测试中进行一些调整。
User.has_usable_password() 和 is_password_usable() 函数不再在密码为 None、空字符串或使用不在 PASSWORD_HASHERS 设置中的哈希器时返回 False。这种未记录的行为是 Django 1.6 中的一个回归,阻止了使用这些密码的用户请求密码重置。审查你的代码以确认你的这些 API 的使用不依赖于旧的行为。
由于迁移现在从 .pyc 文件加载,如果你在混合 Python 2 和 Python 3 环境中工作,你可能需要删除它们。
在 django.contrib.postgres.fields.JSONField 上使用 None 作为查找值现在匹配具有指定键和空值的对象,而不是不具有该键的对象。
管理员的 CSS 类 field-box 已重命名为 fieldBox,以防止与模型字段命名为 "box" 的类发生冲突。
由于现在可以按应用程序或模型覆盖管理员的 actions.html、change_list_results.html、date_hierarchy.html、pagination.html、prepopulated_fields_js.html、search_form.html 和 submit_line.html 模板,因此您可能需要重命名已为不同目的编写的具有这些名称的现有模板。
QuerySet.raw() 现在像常规的查询集一样缓存其结果。如果不想缓存,请使用 iterator()。
数据库路由器的 allow_relation() 方法在更多情况下被调用。不正确编写的路由器可能需要相应地进行更新。
在运行管理命令之前不再停用翻译。如果你的自定义命令需要停用翻译(例如,将未翻译的内容插入数据库),可以使用新的 @no_translations 装饰器。
管理命令不再允许 --settings 和 --pythonpath 参数的缩写形式。
私有常量 django.db.models.sql.constants.QUERY_TERMS 已被移除。 查找注册 API 的 get_lookup() 和 get_lookups() 方法可能是合适的替代方案。与 QUERY_TERMS 常量相比,它们允许您的代码还考虑了已注册的任何自定义查找。
与 py-bcrypt 的兼容性已被移除,因为它已不再维护。请改用 bcrypt。
ForceRHR GIS 函数已被弃用,建议使用新的 ForcePolygonCW 函数。
django.utils.http.cookie_date() 已被弃用,建议使用 http_date(),它遵循最新 RFC 的格式。
{% load staticfiles %} 和 {% load admin_static %} 已被弃用,建议使用 {% load static %},它具有相同的功能。
django.contrib.staticfiles.templatetags.static() 已被弃用,建议使用 django.templatetags.static.static()。
不接受 obj 作为第二个位置参数的 InlineModelAdmin.has_add_permission() 方法的支持将在 Django 3.0 中被移除。
这些功能已经完成了其弃用周期,并在 Django 2.1 中被移除。有关详细信息,包括如何删除这些功能的用法,请参阅 在 1.11 中被废弃的功能。
contrib.auth.views.login(), logout(), password_change(), password_change_done(), password_reset(), password_reset_done(), password_reset_confirm(), 和 password_reset_complete() 已被移除。
contrib.auth.views.logout_then_login() 的 extra_context 参数已被移除。
django.test.runner.setup_databases() 已被移除。
django.utils.translation.string_concat() 已被移除。
django.core.cache.backends.memcached.PyLibMCCache 不再支持将 pylibmc 行为设置作为 OPTIONS 的顶级属性传递。
django.utils.http.is_safe_url() 的 host 参数已被移除。
不再屏蔽在渲染 {% include %} 模板标签时引发的异常。
DatabaseIntrospection.get_indexes() 已被移除。
认证后端的 authenticate() 方法要求将 request 作为第一个位置参数。
django.db.models.permalink() 装饰器已被移除。
USE_ETAGS 设置已被移除。CommonMiddleware 和 django.utils.cache.patch_response_headers() 不再设置 ETags。
Model._meta.has_auto_field 属性已被移除。
url() 对正则表达式组中的内联标志((?i)、(?L)、(?m)、(?s) 和 (?u))的支持已被移除。
不再支持没有 renderer 参数的 Widget.render() 方法。
8月 13, 2025