2017 年 12 月 2 日
欢迎来到 Django 2.0 版本!
这些发布说明涵盖了 新特性,以及从 Django 1.11 或更早版本升级时需要注意的一些 不兼容的变更。我们已经 删除了一些已经达到了弃用周期末尾的功能,并且我们已经 开始了一些功能的弃用过程。
这个发布版本开始使用了 Django 的一种 松散形式的语义版本,但并没有出现与 2.0 版本发布相符的重大不兼容变更。升级应该与过去的功能发布相似的努力。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
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 2.0 发布之后,我们建议第三方应用程序的作者停止支持 1.11 之前的所有 Django 版本。在那个时候,你应该能够使用 python -Wd
运行你包的测试,以便弃用警告会出现。在进行弃用警告修复后,你的应用程序应该与 Django 2.0 兼容。
新版本 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()
中获取。前者依然保留,向后兼容,并没有立即弃用。旧版本中的 django.conf.urls.include()
函数现在可以从 django.urls
中导入,这样你就可以在 URLconfs 中使用 from django.urls import include, path, re_path
。
重新编写的文档 URL调度器 涵盖了新的语法并且提供了更多的细节。
contrib.admin
针对移动设备的优化改进¶新版本的 admin 可以响应和支持所有主流移动设备。较旧的浏览器可能会遇到不同程度的功能降低。
django.contrib.admin
¶新的 ModelAdmin.autocomplete_fields
属性和 ModelAdmin.get_autocomplete_fields()
方法允许在 ForeignKey
和 ManyToManyField
上使用 Select2 搜索小部件。
django.contrib.auth
¶PBKDF2 密码散列器的默认迭代计数从 36,000 增加到 100,000。
django.contrib.gis
¶增加了 AsGeoJSON
函数、 GeoHash
函数、IsValid
函数、isvalid
查找、以及 distance lookups 对 MySQL 的支持。
添加了 PostGIS 和 SpatiaLite 支持的两个函数 Azimuth
和 LineLocatePoint
。
现在所有从 GeoJSON 导入的 GEOSGeometry
都设置了其 SRID。
添加了 OSMWidget.default_zoom
属性来自定义地图的默认缩放级别。
允许使用 papsz_options
将 driver-specific creation options 传递给 GDALRaster
对象。
允许在 GDAL 的内部虚拟文件系统中创建 GDALRaster
对象。现在可以将栅格数据从内存中的二进制数据 创建和转换。
新的 GDALBand.color_interp()
方法返回了该波段的颜色解释。
django.contrib.postgres
¶对于 ArrayAgg
,新的 distinct
参数确定连接的值是否是不同的。
新的 RandomUUID
数据库函数返回版本 4 的 UUID。它需要使用 PostgreSQL 的 pgcrypto
扩展,可以通过新的 CryptoExtension
迁移操作来激活。
django.contrib.postgres.indexes.GinIndex
现在支持 fastupdate
和 gin_pending_list_limit
参数。
新的 GistIndex
类允许在数据库中创建 GiST
索引。新的 BtreeGistExtension
迁移操作安装了 btree_gist
扩展,以添加对不是内置的操作符类的支持。
inspectdb
现在可以内省 JSONField
和各种 RangeField
(必须将 django.contrib.postgres
添加到 INSTALLED_APPS
中)。
django.contrib.sitemaps
¶在 GenericSitemap
构造函数中添加了 protocol
关键字参数。
cache.set_many()
现在返回一个未能插入的键的列表。对于内置的后端,失败的插入只会发生在 memcached 上。
File.open()
可以作为上下文管理器使用,例如 with file.open() as f:
。
对于 SplitDateTimeWidget
和 SplitHiddenDateTimeWidget
,新的 date_attrs
和 time_attrs
参数允许指定不同的 HTML 属性用于 DateInput
和 TimeInput
(或隐藏)子部件。
新的 Form.errors.get_json_data()
方法返回适用于包含在 JSON 响应中的表单错误的字典。
新属性 ContextMixin.extra_context
允许在 View.as_view()
添加上下文。
inspectdb
现在将 MySQL 的无符号整数列翻译为 PositiveIntegerField
或 PositiveSmallIntegerField
。
新的 makemessages --add-location
选项控制 .po
文件中的注释格式。
新的 diffsettings --output
选项允许以统一的差异格式格式化输出。
在 Oracle 上,inspectdb
现在可以内省 AutoField
,如果列被创建为标识列(identity column)。
在 MySQL 上,dbshell
现在支持客户端端的 TLS 证书。
新的 squashmigrations --squashed-name
选项允许命名合并后的迁移。
新的 StrIndex
数据库函数用于查找一个字符串在另一个字符串中的起始索引。
在 Oracle 上,现在会将 AutoField
和 BigAutoField
创建为 标识列。
QuerySet.iterator()
的新参数 chunk_size
控制在从数据库流式传输结果时由 Python 数据库客户端提取的行数。对于不支持服务器端游标的数据库,它控制 Django 从数据库适配器提取的结果数量。
QuerySet.earliest()
、QuerySet.latest()
和 Meta.get_latest_by
现在允许按多个字段排序。
新增了 ExtractQuarter
函数,用于从 DateField
和 DateTimeField
中提取季度,并通过 quarter
查找公开。
新增了 TruncQuarter
函数,用于将 DateField
和 DateTimeField
截断到季度的第一天。
为基于类的索引添加了 db_tablespace
参数。
如果数据库支持原生的持续时间字段(Oracle 和 PostgreSQL),Extract
现在可以与 DurationField
一起使用。
新增了 of
参数到 QuerySet.select_for_update()
,在 PostgreSQL 和 Oracle 上支持,可以锁定特定表中的行,而不是所有选定的表。这在特别是当 select_for_update()
与 select_related()
结合使用时可能会有所帮助。
QuerySet.in_bulk()
的新参数 field_name
允许根据任何唯一模型字段获取结果。
CursorWrapper.callproc()
现在可以接受一个可选的关键字参数字典,如果后端支持此功能。Django 内置的后端中,只有 Oracle 支持这个功能。
内置聚合函数的新 filter
参数允许在同一字段或关系上的多个聚合中 添加不同的条件。
在 Meta.ordering
中添加了对表达式的支持。
QuerySet.values_list()
的新参数 named
允许将结果作为命名元组获取。
新的 FilteredRelation
类允许在查询集中添加一个 ON
子句。
添加了 Paginator.get_page()
,以提供处理无效页码的文档化模式。
runserver
Web 服务器支持 HTTP 1.1。
为了增加第三方应用程序中 Engine.get_default()
的实用性,如果在 TEMPLATES
中配置了多个 DjangoTemplates
引擎,它现在将返回第一个引擎,而不是引发 ImproperlyConfigured
异常。
现在自定义模板标签可以接受仅限关键字的参数。
向 LiveServerTestCase
添加了多线程支持。
添加了允许自定义 Oracle 测试表空间参数的设置:DATAFILE_SIZE
、DATAFILE_TMP_SIZE
、DATAFILE_EXTSIZE
和 DATAFILE_TMP_EXTSIZE
。
新的 ProhibitNullCharactersValidator
在 CharField
表单字段及其子类的输入中禁止使用空字符。空字符输入是由于漏洞扫描工具而观察到的。大多数数据库会悄悄地丢弃空字符,但是当尝试将空字符保存到 PostgreSQL 的 char/text 字段时,psycopg2 2.7+ 会引发异常。
为了支持原生的 Python 2 字符串,旧版本的 Django 必须同时接受字节字符串和 Unicode 字符串。现在 Python 2 的支持已被移除,字节字符串应该只出现在输入/输出边界(例如处理二进制字段或 HTTP 流)附近。您可能需要更新您的代码,以将字节字符串的使用限制到最低,因为 Django 不再在某些代码路径中接受字节字符串。Python 的 -b
选项可能有助于检测代码中的这种错误。
例如,现在 reverse()
在将接收到的 args
和 kwargs
放置在 URL 之前,使用 str()
而不是 force_text()
来强制转换它们。对于字节字符串,这会创建一个带有不希望的 b
前缀以及额外引号的字符串(str(b'foo')
是 "b'foo'"
)。为了适应这种变化,在将字节字符串传递给 reverse()
之前,请调用 decode()
。
本节介绍了第三方数据库后端可能需要的更改。
现在,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
表达式的支持,请将 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
函数中将用于 CharField
的数据库数据类型。
DatabaseCreation._clone_test_db()
和 get_test_db_clone_settings()
的第一个参数现在是 suffix
,而不再是 number``(如果您希望为了一致性而在您的后端中重命名签名)。``django.test
现在也将这些值作为字符串而不是整数传递。
第三方数据库后端应该基于 BaseDatabaseIntrospection
中的存根添加一个名为 DatabaseIntrospection.get_sequences()
的方法。
Oracle 11.2 的上游支持将于 2020 年 12 月结束。 Django 1.11 将在 2020 年 4 月之前得到支持,几乎达到了这个日期。 Django 2.0 正式支持 Oracle 12.1 及更高版本。
MySQL 的默认隔离级别,可重复读(repeatable read),在典型的 Django 使用中可能会导致数据丢失。为了防止这种情况并保持与其他数据库的一致性,现在默认的隔离级别是读提交(read committed)。如果需要,您可以使用 DATABASES
设置来 使用不同的隔离级别。
AbstractUser.last_name
的 max_length
增加到了 150。¶包含了 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()
会导致意外的结果,因为切片是在重新排序后应用的。现在已禁止这样使用,例如:
>>> 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")
如果尝试保存违反外键约束的现有模型实例,将会出现不兼容的后向变更(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
和 RenameField
操作。为了允许应用包含这些操作的迁移,您必须将 Migration.atomic
属性设置为 False
。
SessionAuthenticationMiddleware
类已被移除。自 Django 1.10 版本起,它不再提供任何功能,因为会话身份验证已无条件启用。
默认的 HTTP 错误处理程序(handler404
等)现在是可调用函数,而不再是点分 Python 路径字符串。Django 更倾向于可调用引用,因为它们提供更好的性能和调试体验。
RedirectView
不再在 pattern_name
不存在时抑制 NoReverseMatch
。
当 USE_L10N
关闭时,FloatField
和 DecimalField
现在在验证过程中会尊重 DECIMAL_SEPARATOR
和 THOUSAND_SEPARATOR
。例如,使用以下设置:
USE_L10N = False
USE_THOUSAND_SEPARATOR = True
DECIMAL_SEPARATOR = ","
THOUSAND_SEPARATOR = "."
输入值 "1.345"
现在被转换为 1345
,而不是 1.345
。
AbstractBaseUser
的子类不再需要实现 get_short_name()
和 get_full_name()
。(已删除引发 NotImplementedError
的基本实现。)如果实现了这些方法,django.contrib.admin
将使用它们,但不再要求它们。使用这些方法的第三方应用程序可能希望采用类似的方法。
FIRST_DAY_OF_WEEK
和 NUMBER_GROUPING
格式设置现在在 JavaScript 和 JSON i18n 视图输出中保持为整数。
assertNumQueries()
现在忽略连接配置查询。以前,如果一个测试打开了一个新的数据库连接,那些查询可能会被包括在 assertNumQueries()
计数中。
Oracle 测试表空间的默认大小从 20M 增加到 50M,自动扩展的默认大小从 10M 增加到 25M 。
为了提高从数据库流式传输大型结果集的性能,QuerySet.iterator()
现在一次获取 2000 行,而不是 100 行。可以使用 chunk_size
参数恢复旧的行为。例如:
Book.objects.iterator(chunk_size=100)
在 JavaScriptCatalog
视图的 packages
参数中提供未知的包名称现在会引发 ValueError
,而不是默默通过。
现在,默认的 Model.__str__()
方法中会显示模型实例的主键,例如 Question object (1)
。
现在,makemigrations
会检测到模型字段的 limit_choices_to
选项的更改。请将其添加到现有的迁移中,或接受为使用它的字段生成的自动生成的迁移。
在 MySQL 上执行需要 自动空间转换 的查询现在会引发 NotImplementedError
,而不再默默地使用未经转换的几何图形。
移除了 django.core.exceptions.DjangoRuntimeWarning
。它只在缓存后端中用作 CacheKeyWarning
继承 RuntimeWarning
的中间类。
将 BaseExpression._output_field
重命名为 output_field
。您可能需要更新自定义表达式。
在旧版本中,表单和表单集通过连接两者的 Media
来合并小部件的 Media
。现在,合并尝试 保持每个列表中元素的相对顺序。如果无法保持顺序,将发出 MediaOrderConflictWarning
警告。
移除了 django.contrib.gis.gdal.OGRException
。自 Django 1.8 起,它一直是 GDALException
的别名。
不再支持 GEOS 3.3.x 版本。
选择 GeometryField
的数据的方式已更改以提高性能,在原始 SQL 查询中,现在必须将这些字段包装在 connection.ops.select
中。请参阅 GIS 教程中的 原始查询注意事项 以获取示例。
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()
。render()
接受与之前相同的参数,只是现在需要传递一个 request
参数。
DEFAULT_CONTENT_TYPE
设置已被弃用。它与第三方应用程序的兼容性不佳,并且自 HTML5 大多代替了 XHTML 后已过时。
HttpRequest.xreadlines()
已被弃用,建议改为迭代请求对象。
QuerySet.earliest()
和 QuerySet.latest()
中的 field_name
关键字参数已被弃用,推荐将字段名称作为参数传递。请使用 .earliest('pub_date')
而不是 .earliest(field_name='pub_date')
。
这些功能已经完成了废弃周期,并在 Django 2.0 中被移除。
有关这些更改的详细信息,包括如何删除对这些特性的使用,请参阅 在 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 中被废弃的功能 以获取有关这些更改的详细信息。
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
的老式中间件。
4月 27, 2025