Categories
程式開發

Django 3.1发布,支持异步 view 和 middleware


Django 3.1已于8月4日正式发布,官方文档更新了发布说明,全文翻译如下。

本发行说明涵盖了新版中的各项新功能,以及从Django 3.0或更早版本升级时需要注意的一些向后不兼容的更改。我们删除了一些已完全弃用的功能,并且开始了某些功能的弃用流程。

如果要更新现有项目,请参阅”将Django升级到较新版本”的指南

Python兼容性

Django 3.1支持Python 3.6、3.7和3.8。我们 强烈建议 并且仅正式支持每个系列的最新版本。

Django 3.1的新功能

异步视图和中间件支持

Django现在支持完全异步的请求路径,包括:

  • 异步视图
  • 异步中间件
  • 异步测试和测试客户端

要使用异步视图,你需要用async def声明一个视图:

async def my_view(request): 
    await asyncio.sleep(0.5) 
    return HttpResponse('Hello, async world!') 

无论你是在WSGI还是ASGI模式下运行,都支持所有异步功能。但是,在WSGI模式下使用异步代码会导致性能下降。你可以在异步支持文档中了解更多信息
你可以随意混合使用异步和同步视图、中间件和测试。Django将确保你一直拥有正确的执行上下文。我们预计大多数项目的大部分视图还会是同步的,只有少数几个运行在异步模式下——但这完全取决于你自己。

Django的ORM、缓存层和其他长时间运行网络调用的代码尚不支持异步访问。我们预计在即将发布的版本中增加对它们的支持。异步视图是理想的选择,但如果你要在视图中进行大量API或HTTP调用,则现在可以并行执行所有这些HTTP调用,从而显著加快视图的执行速度。

异步支持应该是完全向后兼容的,并且我们基本能保证现有的同步代码不会有速度下降。它对任何现有的Django项目都没有明显的影响。

用于所有支持的数据库后端的JSONField

Django现在包括models.JSONField和forms.JSONField,可在所有受支持的数据库后端上使用。这两个字段都支持使用自定义JSON编码器和解码器。model字段支持以前仅适用于PostgreSQL的introspection、lookup和transform:

from django.db import models 
class ContactInfo(models.Model): 
    data = models.JSONField() 
ContactInfo.objects.create(data={ 
    'name': 'John', 
    'cities': ['London', 'Cambridge'], 
    'pets': {'dogs': ['Rufus', 'Meg']}, 
}) 
ContactInfo.objects.filter( 
    data__name='John', 
    data__pets__has_key='dogs', 
    data__cities__contains='London', 
).delete() 

如果你的项目使用django.contrib.postgres.fields.JSONField以及相关的表单字段和转换,则应进行调整以使用新字段,并生成和应用数据库迁移。目前,旧的字段和转换保留为对新字段和转换的引用,并且在此版本中已弃用。

DEFAULT_HASHING_ALGORITHM设置

新的DEFAULT_HASHING_ALGORITHM过渡设置允许指定默认的哈希算法,用于编码cookie、管理员站点中的密码重置令牌、用户会话以及django.core.signing.Signer和django.core.signing.dumps()创建的签名。

Django 3.1中还添加了对SHA-256的支持。如果要将同一项目的多个实例升级到Django 3.1,则应在迁移期间将DEFAULT_HASHING_ALGORITHM设置为“sha1”,以兼容Django的较早版本。到3.1的迁移完成后,你可以停止覆盖DEFAULT_HASHING_ALGORITHM。

此设置在这个版本中已弃用,因为在Django 4.0中将删除对使用SHA-1算法的令牌、cookie、会话和签名的支持。

次要功能

django.contrib.admin

  • 新的用于ModelAdmin.list_filter的django.contrib.admin.EmptyFieldListFilter允许在管理员更改列表视图中过滤空值(空字符串和null)。
  • 现在,管理员更改列表视图右侧栏中的过滤器包含一个链接,可清除所有过滤器。
  • 现在,在较大的屏幕上为管理员提供了侧边栏,以方便导航。它是默认启用的,但可以使用自定义AdminSite并将AdminSite.enable_nav_sidebar设置为False来禁用它。

渲染侧栏需要访问当前请求才能设置CSS和ARIA角色权限。这需要在OPTIONS的“context_processors”选项中使用“django.template.context_processors.request”。

  • XRegExp已从2.0.0版本升级到3.2.0。
  • jQuery从版本3.4.1升级到3.5.1。
  • Select2库从版本4.0.7升级到4.0.13。

django.contrib.auth¶

  • PBKDF2密码哈希器的默认迭代计数从180,000增加到216,000。
  • 新的PASSWORD_RESET_TIMEOUT设置允许定义密码重置链接有效的秒数。鼓励使用此选项,不建议使用PASSWORD_RESET_TIMEOUT_DAYS设置,后者将在Django 4.0中删除。
  • 密码重置机制现在使用SHA-256哈希算法。对使用旧哈希算法的令牌的支持一直保留到Django 4.0。
  • 现在,AbstractBaseUser.get_session_auth_hash()使用SHA-256哈希算法。直到Django 4.0为止,仍支持使用旧哈希算法的用户会话。

django.contrib.contenttypes

  • 新的remove_stale_contenttypes–include-stale-apps选项允许从之前安装的应用程序(已从INSTALLED_APPS中删除)中删除过时的内容类型。

django.contrib.gis

  • MariaDB现在支持relate查找。
  • 添加了LinearRing.is_counterclockwise属性。
  • Oracle现在支持AsGeoJSON。
  • 添加了AsWKB和AsWKT函数。
  • 添加了对PostGIS3和GDAL3的支持。

django.contrib.humanize¶

  • intword模板过滤器现在支持负整数。

django.contrib.postgres¶

  • 新的BloomIndex类允许在数据库中创建Bloom索引。新的BloomExtension迁移操作将安装Bloom扩展以添加对该索引的支持。
  • get_FOO_display()现在支持ArrayField和RangeField。
  • 新的rangefield.lower_inc、rangefield.lower_inf、rangefield.upper_inc和rangefield.upper_inf查找允许按绑定类型查询RangeField。
  • rangefield.contained_by现在支持SmallAutoField、AutoField、BigAutoField、SmallIntegerField和DecimalField。
  • SearchQuery现在在PostgreSQL 11+上支持”websearch”搜索类型。
  • SearchQuery.value现在支持查询表达式。
  • 新的SearchHeadline类允许高亮显示搜索结果。
  • search查找现在支持查询表达式。
  • SearchRank的新cover_density参数允许按覆盖密度排名。
  • SearchRank的新normalization参数允许进行排名规范化。
  • 新的ExclusionConstraint.deferrable属性允许创建可延期的排除约束。

django.contrib.sessions

  • 现在,SESSION_COOKIE_SAMESITE设置允许“None”(字符串)值,明确声明Cookie是与所有相同站点和跨站点请求一起发送的。

django.contrib.staticfiles

  • STATICFILES_DIRS设置现在支持pathlib.Path。

Cache

  • 现在,根据RFC7234#section-5.2.2.2,cache_control()装饰器和patch_cache_control()方法在Cache-Control标头的no-cache指令中支持多个字段名称。
  • 如果成功删除键,delete()现在返回True,否则返回False。

CSRF

  • CSRF_COOKIE_SAMESITE设置现在允许“None”(字符串)值,明确声明该cookie是与所有相同站点和跨站点请求一起发送的。

Email

  • 文件电子邮件后端使用的EMAIL_FILE_PATH设置现在支持pathlib.Path。

错误报告

  • django.views.debug.SafeExceptionReporterFilter现在可以过滤异常报告中request.META中的敏感值。
  • 新的SafeExceptionReporterFilter.cleansed_substitute和SafeExceptionReporterFilter.hidden_​​settings属性允许自定义敏感设置和异常报告中的request.META筛选。
  • 现在,在应用设置过滤时,技术性404调试视图会遵循DEFAULT_EXCEPTION_REPORTER_FILTER。
  • 新的DEFAULT_EXCEPTION_REPORTER允许提供django.views.debug.ExceptionReporter子类来自定义生成异常报告。有关详细信息,请参见自定义错误报告

文件存储

  • FileSystemStorage.save()方法现在支持pathlib.Path。
  • FileField和ImageField现在接受可调用的storage。这样,你可以在运行时修改已使用的storage,例如为不同的环境选择不同的存储。

格式

  • 现在,ModelChoiceField和ModelMultipleChoiceField使用的ModelChoiceIterator使用ModelChoiceIteratorValue,小部件可以使用ModelChoiceIteratorValue来访问模型实例。有关详细信息,请参见迭代关系选择
  • django.forms.DateTimeField现在接受ISO 8601日期时间格式的子集中的日期,包括可选的时区,例如2019-10-10T06:47、2019-10-10T06:47:23+04:00或2019-10-10T06:47:23Z。如果提供了时区,则将始终保留该时区,即使USE_TZ为False,也会返回时区调整后的日期时间。

此外,在将字段输入转换为日期时间值时,DateTimeField现在除了DATETIME_INPUT_FORMATS之外还使用DATE_INPUT_FORMATS。

  • MultiWidget.widgets现在接受一个字典,该字典允许自定义子小部件的name属性。
  • 新的BoundField.widget_type属性可用于根据小部件类型动态调整格式渲染。

国际化

  • 现在,LANGUAGE_COOKIE_SAMESITE设置允许“None”(字符串)值,明确声明Cookie是与所有相同站点和跨站点请求一起发送的。
  • 增加了对阿尔及利亚阿拉伯语、伊博语、吉尔吉斯语、塔吉克语和土库曼语的支持和翻译。

管理命令

  • 新的check–database选项允许指定数据库别名以运行database系统检查。以前,将database标签传递给命令,可以为所有已配置的DATABASES启用这些检查。
  • 当检测到未应用的迁移时,新的migration–check选项使命令以非零状态退出。
  • CommandError的新returncode参数允许自定义管理命令的退出状态。
  • 新的dbshel​​l-ARGUMENTS选项允许将额外的参数传递给数据库的命令行客户端。
  • 现在,flush和sqlflush命令包括了SQL来重置SQLite上的序列。

模式

  • 新的ExtractIsoWeekDay函数从DateField和DateTimeField中提取ISO-8601工作日,新的iso_week_day查找允许按ISO-8601工作日查询。
  • QuerySet.explain()现在支持:
    • MySQL 8.0.16+上的TREE格式,
    • MySQL8.0.18+和MariaDB上的analyzer选项。
  • 添加了PositiveBigIntegerField,它的行为与PositiveIntegerField相似,不同之处在于它只允许特定(与数据库有关)限制内的值。在Django支持的所有数据库中,0到9223372036854775807的值都是安全的。
  • ForeignKey和OneToOneField的on_delete参数的新RESTRICT选项可模拟SQL约束ONDELETERESTRICT的行为。
  • CheckConstraint.check现在支持布尔表达式。
  • 现在,RelatedManager.add()、create()和set()方法接受可调用对象作为through_defaults参数中的值。
  • QuerySet.datetimes()的新is_dst参数可确定不存在和不明确的日期时间的处理方式。
  • 新的F表达式bitxor()方法允许按位XOR操作。
  • 现在,使用MariaDB 10.5+时,QuerySet.bulk_create()设置对象的主键。
  • 现在,对于不需要重置序列的表,使用DELETE而不是TRUNCATE语句后,DatabaseOperations.sql_flush()方法可在MySQL上生成更有效的SQL。
  • SQLite函数现在在Python 3.8+上被标记为deterministic。这样就可以在检查约束和部分索引中使用它们。
  • 新的UniqueConstraint.deferrable属性允许创建可延迟的唯一约束。

分页

  • 现在可以遍历Paginator以产生其页面。

请求和响应

  • 如果ALLOWED_HOSTS为空并且DEBUG=True,则现在在Host标头中允许localhost的子域,例如static.localhost。
  • HttpResponse.set_cookie()和HttpResponse.set_signed_cookie()现在允许使用samesite=‘None’(字符串),来明确声明cookie是与所有相同站点和跨站点请求一起发送的。
  • 新的HttpRequest.accepts()方法根据AcceptHTTP标头,返回请求是否接受给定的MIME类型。

安全

  • SECURE_REFERRER_POLICY设置现在默认为“same-origin”。使用此配置后,SecurityMiddleware会在所有尚未将Referrer Policy标头设置为same-origin的响应上这样设置。这样可以防止将Referer标头发送到其他来源。如果需要以前的行为,请将SECURE_REFERRER_POLICY显式设置为“None”。
  • django.core.signing.Signer、django.core.signing.loads()和django.core.signing.dumps()的默认算法已更改为SHA-256。直到Django 4.0为止,仍支持使用旧SHA-1算法制作的签名。

同样,Signator的新algorithm参数允许自定义哈希算法。

模板

  • 在模板代码中引入了重命名的translate和blocktranslate模板标签,用于国际化用途。较早的trans和blocktrans模板标签别名将继续生效,并在可预见的将来继续保留。
  • 现在,include模板标签可以接受模板名称的可迭代项。

测试

  • SimpleTestCase现在实现debug()方法,以允许运行测试时无需收集结果和捕获异常。这可用于支持在调试器下运行测试。
  • 新的MIGRATE测试数据库设置允许在创建测试数据库期间禁用迁移。
  • Django测试运行器现在支持test–buffer选项,以放弃通过测试的输出。
  • DiscoverRunner现在对测试未引用的数据库跳过系统检查。
  • 由于flush命令的改进,MySQL上的TransactionTestCase清除现在更快。副作用是后者不再会在清除时自动重置序列。如果你的测试需要此功能,请启用TransactionTestCase.reset_sequences。

网址

  • 路径转换器现在可以在to_url()中引发ValueError,以在反向URL时指示不匹配情况。

实用工具

  • filepath_to_uri()现在支持pathlib.Path。
  • parse_duration()现在支持ISO8601格式的小数部分的逗号分隔符。
  • parse_datetime()、parse_duration()和parse_time()现在支持毫秒的逗号分隔。

杂项

  • SQLite后端现在支持NAME设置的pathlib.Path。
  • 现在,由startproject命令生成的settings.py使用pathlib.Path代替os.path来构建文件系统路径。
  • 现在,在支持时区的数据库上允许使用TIME_ZONE设置。

3.1中向后不兼容的更改

数据库后端API

本节描述了第三方数据库后端中可能需要的更改。

  • 现在,DatabaseOperations.fetch_returned_insert_columns()需要一个额外的returning_params参数。
  • 现在,connection.timezone属性默认为“UTC”,或者在支持时区的数据库上,当USE_TZ为True时为TIME_ZONE。以前,它在支持时区的数据库上为None。
  • 新版将connection._nodb_connection属性更改为connection._nodb_cursor()方法,并返回一个上下文管理器,该管理器产生一个游标,并在退出with语句时自动关闭游标和连接。
  • 现在,DatabaseClient.runshell()需要一个额外parameters参数,作为传递给命令行客户端的附加参数。
  • DatabaseOperations.sql_flush()的sequences位置参数由仅布尔型关键字参数reset_sequences取代。如果为True,则将重置截断表的序列。
  • 现在,DatabaseOperations.sql_flush()的allow_cascade参数是仅关键字的参数。
  • DatabaseOperations.execute_sql_flush()的using位置参数已删除。该方法现在使用被调用实例的数据库。
  • 第三方数据库后端必须实现对JSONField的支持,或将DatabaseFeatures.supports_json_field设置为False。如果不支持存储原语,请将DatabaseFeatures.supports_primitives_in_json_field设置为False。如果JSON的数据类型为true,请将DatabaseFeatures.has_native_json_field设置为True。如果不支持jsonfield.contains和jsonfield.contained_by,请将DatabaseFeatures.supports_json_field_contains设置为False。
  • 第三方数据库后端必须实现JSONField的introspection,或将can_introspect_json_field设置为False。

不再支持MariaDB 10.1

对MariaDB 10.1的上游支持将于2020年10月结束。Django 3.1支持MariaDB 10.2和更高版本。

contrib.admin浏览器支持

管理员不再支持旧版Internet Explorer浏览器。有关支持浏览器的详细信息,请参见管理员常见问题解答

AbstractUser.first_namemax_length增加到150

包括django.contrib.auth.models.User.first_name的迁移。如果你的自定义用户模型继承自AbstractUser,则需要为该用户模型生成并应用数据库迁移。

如果要保留名字的30个字符限制,请使用自定义格式:

from django import forms 
from django.contrib.auth.forms import UserChangeForm 
class MyUserChangeForm(UserChangeForm): 
    first_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) 

杂项

  • cache使用的make_template_fragment_key()生成的缓存键与Django较早版本生成的键不同。升级到Django 3.1后,对任何先前缓存的模板片段的第一个请求将是缓存未命中。
  • 现在,从set_language()视图返回重定向回退或204 HTTP响应的决策,背后的逻辑是基于AcceptHTTP标头,而不是X-Requested-WithHTTP标头。
  • django.db.models.query、django.db.models.sql和django.db.models.sql.datastructures中的django.core.exceptions.EmptyResultSet的兼容性导入已删除。
  • django.db.models.fields中django.core.exceptions.FieldDoesNotExist的兼容性导入已删除。
  • django.forms.forms中的django.forms.utils.pretty_name()和django.forms.boundfield.BoundField的兼容性导入已删除。
  • django.template.base中的Context、ContextPopException和RequestContext的兼容性导入已删除。
  • django.contrib.admin中的django.contrib.admin.helpers.ACTION_CHECKBOX_NAME的兼容性导入已删除。
  • 设置为相对路径的STATIC_URL和MEDIA_URL设置现在由服务器提供的SCRIPT_NAME值作为前缀(或/,如果未设置)。此更改不应影响设置为有效URL或绝对路径的设置。
  • ConditionalGetMiddleware不再将ETag标头添加到content为空的响应中。
  • django.utils.decorators.classproperty()装饰器已公开,并移至django.utils.functional.classproperty()。
  • floatformat模板过滤器现在为负数输出(正数)0(四舍五入为零)。
  • 模式上的Meta.ordering和Meta.unique_together选项以前是元组,现在是列表。
  • 现在,管理员日历小部件可根据开放组规范处理两位数的年份,即,将69到99之间的值映射到上一个世纪,将0到68之间的值映射到当前的世纪。
  • 仅日期格式从DATETIME_INPUT_FORMATS的默认列表中删除。
  • 存在初始数据时,FileInput小部件不再使用required HTML属性渲染。
  • 没有文档的django.views.debug.ExceptionReporterFilter类已删除。根据自定义错误报告文档,与DEFAULT_EXCEPTION_REPORTER_FILTER一起使用的类需要从django.views.debug.SafeExceptionReporterFilter继承。
  • 现在,由cache_page()装饰器设置的缓存超时优先于Cache-Control标头中的max-age指令。
  • 现在,在ForeignKey.to_field参数中提供非本地远程字段会引发FieldError。
  • SECURE_REFERRER_POLICY现在默认为“same-origin”。有关详细信息,请参见上面的“安全”部分。
  • checkmanagement命令现在运行database系统,仅检查使用check –database选项指定的数据库别名。
  • 现在,migrate管理命令运行database系统,仅检查要迁移的数据库。
  • 移除了管理员CSS类row1和row2,而使用了:nth-​​child(odd)和:nth-​​child(even)伪类。
  • 现在,make_password()函数要求其参数为字符串或字节。其他类型应显式转换为其中一种。
  • AsKML函数的无文档version参数已删除。
  • 现在,默认情况下,转储数据使用的JSON和YAML序列化器转储所有使用Unicode的数据。如果你需要以前的行为,则将sure_ascii=True传递给JSON序列化器,或者将allow_unicode=False传递给YAML序列化器。
  • 自动重新加载器不再监视Django内置翻译文件中的更改。
  • mysqlclient的最低支持版本从1.3.13增加到1.4.0。
  • 无文档的django.contrib.postgres.forms.InvalidJSONInput和django.contrib.postgres.forms.JSONString已移至django.forms.fields。
  • 删除无文档的django.contrib.postgres.fields.jsonb.JsonAdapter类。
  • {% localize off %}标签和unlocalize过滤器不再遵循DECIMAL_SEPARATOR设置。
  • 受支持的最低版本asgiref从3.2增加到3.2.10。

3.1中已弃用的功能

PostgreSQLJSONField

弃用django.contrib.postgres.fields.JSONField和django.contrib.postgres.forms.JSONField,而应使用models.JSONField和forms.JSONField。
弃用无文档的django.contrib.postgres.fields.jsonb.KeyTransform和django.contrib.postgres.fields.jsonb.KeyTextTransform,而应使用django.db.models.fields.json中的转换。

新的JSONFields、KeyTransform和KeyTextTransform可以在所有受支持的数据库后端上使用。

杂项

  • 弃用PASSWORD_RESET_TIMEOUT_DAYS设置,而应使用PASSWORD_RESET_TIMEOUT。
  • 弃用非布尔值的isnull查找,因为右边已经弃用了,应该使用True或False代替。
  • 弃用几乎无文档的django.db.models.query_utils.InvalidQuery异常类,而应使用FieldDoesNotExist和FieldError。
  • 弃用django-admin.py入口点,而应使用django-admin。
  • 弃用HttpRequest.is_ajax()方法,因为它依赖于表示AJAX调用的jQuery特定方式,而当前用法倾向于使用JavaScript Fetch API。根据你的用例,你可以编写自己的AJAX检测方法,或者如果代码依赖于客户端的Accept HTTP标头,则可以使用新的HttpRequest.accepts()方法。

如果你正在编写自己的AJAX检测方法,则可以完全按照request.headers.get(‘x-requested-with’)==’XMLHttpRequest’的方式复制request.is_ajax()。

  • 将None作为第一个参数传递给django.utils.deprecation.MiddlewareMixin.init()的做法已弃用。
  • CookieStorage使用的cookie值的编码格式与Django较早版本生成的格式不同。对旧格式的支持一直持续到Django 4.0。
  • 会话的编码格式不同于旧版Django生成的格式。对旧格式的支持一直持续到Django 4.0。
  • 用于Signal的纯文档化的providing_args参数已弃用。如果你将此参数用作文档,则可以将文本移至代码注释或文档字符串。
  • 不带length参数的django.utils.crypto.get_random_string()已弃用。
  • 弃用ModelMultipleChoiceField的list消息,应使用invalid_list。
  • 将URL kwargs通过TemplateView直接传递到上下文的做法已弃用。应使用view.kwargs在模板中引用它们。
  • 将原始列别名传递给QuerySet.order_by()的做法已弃用。预先在RawSQL中传递别名可以实现相同的结果。
  • 弃用NullBooleanField模型字段,而应使用BooleanField(null=True)。
  • django.urls.re_path()的django.conf.urls.url()别名已弃用。
  • 弃用{% ifequal %}和{% ifnotequal %}模板标签,而应使用{% if %}。{% if %}涵盖了所有用例,但是如果你需要继续使用这些标记,则可以将它们从Django中提取到模块中,并作为内置标记包含在OPTIONS中的“builtins”选项中。
  • 弃用DEFAULT_HASHING_ALGORITHM过渡设置。

3.1中删除的功能

这些功能已到弃用周期的末端,并已在Django 3.1中删除。

有关这些更改的详细信息,请参阅2.2中弃用的功能,包括如何移除对这些功能的应用。

  • django.utils.timezone.FixedOffset已删除。
  • django.core.paginator.QuerySetPaginator已删除。
  • 模型的Meta.ordering不会影响GROUPBY查询。
  • django.contrib.postgres.fields.FloatRangeField和django.contrib.postgres.forms.FloatRangeField被删除。
  • FILE_CHARSET设置被删除。
  • django.contrib.staticfiles.storage.CachedStaticFilesStorage已删除。
  • RemoteUserBackend.configure_user()方法要求将request作为第一个位置参数。
  • 删除了对SimpleTestCase.allow_database_queries和TransactionTestCase.multi_db的支持。

原文链接: https://docs.djangoproject.com/en/3.1/releases/3.1/