Django 2.0发行说明

2017年12月2日

欢迎来到Django 2.0!

这些发行说明涵盖了 new features 以及一些 backwards incompatible changes 从django 1.11或更早版本升级时,您需要注意。我们已经 dropped some features 已经到了他们的折旧周期结束,我们已经 begun the deprecation process for some features .

此版本开始Django使用 loose form of semantic versioning 但是没有任何主要的向后不兼容的变更,这可能是2.0版本的预期结果。升级的工作量应该与以前的功能版本相当。

如何将Django升级到更新版本 如果正在更新现有项目,则提供指南。

python兼容性

Django2.0支持python 3.4、3.5、3.6和3.7。我们 强烈推荐 只有官方支持每个系列的最新版本。

django 1.11.x系列是最后一个支持python 2.7的系列。

Django2.0将是支持Python3.4的最后一个发行版系列。如果您计划在Django 2.0(2019年4月)的生命周期结束后部署python 3.4,请改为使用Django 1.11 LTS(支持到2020年4月)。但是请注意,Python3.4的生命周期结束于2019年3月。

第三方库支持旧版本的Django

在Django2.0发布之后,我们建议第三方应用程序作者放弃对1.11之前所有版本的Django的支持。那时,您应该能够使用 python -Wd 这样就出现了反预测警告。在修复了拒绝警告之后,您的应用程序应该与Django 2.0兼容。

Django 2.0的新功能

简化的URL路由语法

新的 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 关键字参数是整数而不是字符串。另外,在重写的示例中,将匹配的URL受到的约束也稍微小一些。例如,10000年现在将匹配,因为年份整数不受限制为正好四位数,只要它们在正则表达式中。

这个 django.conf.urls.url() 以前版本的函数现在可用为 django.urls.re_path() . 旧位置保持向后兼容性,而不会立即遭到拒绝。老年人 django.conf.urls.include() 函数现在可从导入 django.urls 所以你可以使用 from django.urls import include, path, re_path 在你的家庭里。

这个 URL调度器 文档将被重写,以适应新的语法并提供更多详细信息。

手机友好 contrib.admin

管理员现在可以响应并支持所有主要的移动设备。较旧的浏览器可能会经历不同程度的优雅降级。

窗口表达式

新的 Window 表达式允许添加 OVER 子句到查询集。你可以使用 window functionsaggregate functions 在表达式中。

次要特征

django.contrib.admin

django.contrib.auth

  • pbkdf2密码散列器的默认迭代计数从36000增加到100000。

django.contrib.gis

django.contrib.postgres

  • 新的 distinct 的参数 ArrayAgg 确定连接的值是否不同。

  • 新的 RandomUUID 数据库函数返回版本4 UUID。它需要使用PostgreSQL pgcrypto 可使用新的 CryptoExtension 迁移操作。

  • django.contrib.postgres.indexes.GinIndex 现在支持 fastupdategin_pending_list_limit 参数。

  • 新的 GistIndex 类允许创建 GiST 数据库中的索引。新的 BtreeGistExtension 迁移操作安装 btree_gist 扩展以添加对非内置运算符类的支持。

  • inspectdb 现在可以反省 JSONField 和各种 RangeField 的S (django.contrib.postgres 必须在 INSTALLED_APPS

django.contrib.sitemaps

隐藏物

  • cache.set_many() 现在返回插入失败的键列表。对于内置后端,失败的插入只能在memcached上发生。

文件存储

  • File.open() 可以用作上下文管理器,例如 with file.open() as f: .

形式

通用视图

管理命令

迁徙

模型

分页

请求和响应

  • 这个 runserver Web服务器支持HTTP1.1。

模板

  • 提高 Engine.get_default() 在第三方应用程序中,如果有多个引擎,它现在返回第一个引擎 DjangoTemplates 引擎配置在 TEMPLATES 而不是提高 ImproperlyConfigured .

  • 自定义模板标记现在可以只接受关键字参数。

测验

验证器

  • 新的 ProhibitNullCharactersValidator 不允许在 CharField 窗体域及其子类。从漏洞扫描工具中观察到空字符输入。大多数数据库都会悄悄地丢弃空字符,但是psycopg2 2.7+在尝试用postgresql将空字符保存到char/text字段时引发异常。

2.0中的向后不兼容更改

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

为了支持本机python2字符串,旧的Django版本必须同时接受bytestrings和Unicode字符串。现在Python2支持被放弃了,bytestrings应该只在输入/输出边界附近遇到(例如,处理二进制字段或HTTP流)。您可能需要更新代码以将bytestring的使用限制在最低限度,因为Django不再接受某些代码路径中的bytestrings。 Python 的 -b 选项可以帮助检测代码中的错误。

例如, reverse() 现在使用 str() 而不是 force_text() 胁迫 argskwargs 它会在它们放置在URL中之前接收它们。对于bytestrings,这将创建一个带有不需要的字符串 b 前缀和附加引号 (str(b'foo')"b'foo'" )适应,呼唤 decode() 在把它传递给 reverse() .

数据库后端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 表达式,集 DatabaseFeatures.supports_over_clauseTrue . 您可能需要自定义 DatabaseOperations.window_start_rows_start_end() 和/或 window_start_range_start_end() 方法。

  • 第三方数据库后端应添加 DatabaseOperations.cast_char_field_without_max_length 属性的数据库数据类型将在 Cast A函数 CharField 如果 max_length 未提供参数。

  • 第一个论点 DatabaseCreation._clone_test_db()get_test_db_clone_settings() 现在是 suffix 而不是 number (以防为了一致性而重命名后端中的签名)。 django.test 现在也将这些值作为字符串而不是整数传递。

  • 第三方数据库后端应添加 DatabaseIntrospection.get_sequences() 基于存根的方法 BaseDatabaseIntrospection .

放弃对Oracle 11.2的支持

Oracle 11.2的上游支持将于2020年12月结束。Django 1.11将得到支持,直到2020年4月,几乎达到这个日期。Django 2.0正式支持Oracle 12.1+。

默认MySQL隔离级别为“读提交”

MySQL的默认隔离级别(repeatable read)在典型的django使用中可能会导致数据丢失。为了防止这种情况发生并保持与其他数据库的一致性,现在默认的隔离级别是读提交。你可以使用 DATABASES 设置为 use a different isolation level ,如果需要的话。

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")

现在在sqlite上启用了外键约束

这将显示为向后不兼容的更改 (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的表修改限制,禁止执行 RenameModelRenameField 对事务中其他模型引用的模型或字段的操作。为了允许应用包含这些操作的迁移,必须设置 Migration.atomic 属性到 False .

其他

  • 这个 SessionAuthenticationMiddleware 类被删除。由于在Django 1.10中无条件地启用了会话身份验证,因此它没有提供任何功能。

  • 默认的HTTP错误处理程序 (handler404 等等)现在是可调用的,而不是点状的python路径字符串。Django支持可调用引用,因为它们提供了更好的性能和调试经验。

  • RedirectView 不再沉默 NoReverseMatch 如果 pattern_name 不存在。

  • 什么时候 USE_L10N 已关闭, FloatFieldDecimalField 现在请尊重 DECIMAL_SEPARATORTHOUSAND_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_WEEKNUMBER_GROUPING 格式设置现在在javascript和json i18n视图输出中保持为整数。

  • assertNumQueries() 现在忽略连接配置查询。以前,如果测试打开了一个新的数据库连接,那么这些查询可以作为 assertNumQueries() 伯爵。

  • Oracle测试表空间的默认大小从20米增加到50米,默认的自动扩展大小从10米增加到25米。

  • 为了提高从数据库中流式处理大型结果集时的性能, QuerySet.iterator() 现在一次提取2000行而不是100行。可以使用 chunk_size 参数。例如::

    Book.objects.iterator(chunk_size=100)
    
  • 在中提供未知的包名称 packages 论证 JavaScriptCatalog 视图现在升高 ValueError 而不是静静地走过。

  • 模型实例的主键现在显示在默认值中 Model.__str__() 方法,例如 Question object (1) .

  • makemigrations 现在检测模型字段的更改 limit_choices_to 选择权。将其添加到现有迁移中,或者接受使用它的字段的自动生成迁移。

  • 执行需要的查询 automatic spatial transformations 现在提出 NotImplementedError 在mysql上,而不是静默地使用未转换的几何体。

  • django.core.exceptions.DjangoRuntimeWarning 被移除。它仅在缓存后端中用作 CacheKeyWarning 的继承权 RuntimeWarning .

  • 更名 BaseExpression._output_fieldoutput_field . 可能需要更新自定义表达式。

  • 在旧版本中,表单和表单集结合了 Media 使用控件 Media 将两者串联起来。组合现在试图 preserve the relative order of elements in each list . MediaOrderConflictWarning 如果订单无法保存,则发出。

  • django.contrib.gis.gdal.OGRException 被移除。它是 GDALException 从Django 1.8开始。

  • 不再支持geos 3.3.x。

  • 数据的选择方式 GeometryField 更改以提高性能,在原始SQL查询中,现在必须将这些字段包装在 connection.ops.select . 见 Raw queries note 以GIS教程为例。

2.0中不推荐的功能

context argument of Field.from_db_value() and Expression.convert_value()

这个 context 的参数 Field.from_db_value()Expression.convert_value() 未使用,因为它总是一本空字典。这两种方法的签名现在是:

(self, value, expression, connection)

而不是::

(self, value, expression, connection, context)

在Django3.0之前,对自定义字段和表达式中旧签名的支持仍然存在。

其他

  • 这个 django.db.backends.postgresql_psycopg2 模块已弃用,取而代之的是 django.db.backends.postgresql . 从Django 1.9开始,它就是一个别名。这只影响直接从模块导入的代码。这个 DATABASES 设置仍可以使用 'django.db.backends.postgresql_psycopg2' 尽管您可以通过使用 'django.db.backends.postgresql' 在Django 1.9中添加的名称。

  • django.shortcuts.render_to_response() 被否决,赞成 django.shortcuts.render() . render() 采用相同的参数,但它还需要 request .

  • 这个 DEFAULT_CONTENT_TYPE 设置已弃用。它与第三方应用程序的交互不好,而且已经过时了,因为HTML5已经取代了XHTML。

  • HttpRequest.xreadlines() 已弃用,赞成对请求进行迭代。

  • 这个 field_name 关键字参数 QuerySet.earliest()QuerySet.latest() 不赞成将字段名作为参数传递。写 .earliest('pub_date') 而不是 .earliest(field_name='pub_date') .

在2.0中删除的功能

这些功能已达到其折旧周期的末尾,并在Django 2.0中删除。

1.9中不推荐的功能 有关这些更改的详细信息,包括如何删除这些功能的用法。

  • 这个 weak 参数 django.dispatch.signals.Signal.disconnect() 被移除。

  • django.db.backends.base.BaseDatabaseOperations.check_aggregate_support() 被移除。

  • 这个 django.forms.extras 包已删除。

  • 这个 assignment_tag 助手已删除。

  • 这个 host 参数 SimpleTestCase.assertsRedirects() 被移除。当路径相同时,允许绝对URL被视为等于相对URL的兼容性层也被删除。

  • Field.relField.remote_field.to 被移除。

  • 这个 on_delete 的参数 ForeignKeyOneToOneField 现在在模型和迁移中是必需的。考虑挤压迁移,这样更新的迁移就更少了。

  • django.db.models.fields.add_lazy_relation() 被移除。

  • 当启用时区支持时,不支持时区的数据库后端不再以UTC格式将已知日期时间转换为原始值,当这些值作为参数传递给在ORM外部执行的SQL查询时,例如使用 cursor.execute() .

  • django.contrib.auth.tests.utils.skipIfCustomUser() 被移除。

  • 这个 GeoManagerGeoQuerySet 类被删除。

  • 这个 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_templateload_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 参数已删除。

  • 这个 mime_type 属性 django.utils.feedgenerator.Atom1Feeddjango.utils.feedgenerator.RssFeed 被移除。

  • 这个 app_name 参数 include() 被移除。

  • 支持传递3元组(包括 admin.site.urls )作为第一个论点 include() 被移除。

  • 已删除对设置没有应用程序命名空间的URL实例命名空间的支持。

  • Field._get_val_from_obj() 被移除。

  • django.template.loaders.eggs.Loader 被移除。

  • 这个 current_app 参数 contrib.auth 基于函数的视图将被删除。

  • 这个 callable_obj 关键字参数 SimpleTestCase.assertRaisesMessage() 被移除。

  • 支持 allow_tags 属性对 ModelAdmin 方法被移除。

  • 这个 enclosure 关键字参数 SyndicationFeed.add_item() 被移除。

  • 这个 django.template.loader.LoaderOrigindjango.template.base.StringOrigin 用于别名 django.template.base.Origin 被移除。

1.10中不推荐的功能 有关这些更改的详细信息。

  • 这个 makemigrations --exit 选项被删除。

  • 取消了对反向外键或多对多关系的直接分配的支持。

  • 这个 get_srid()set_srid() 方法 django.contrib.gis.geos.GEOSGeometry 被移除。

  • 这个 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.Point 被移除。

  • 这个 cascaded_union 性质 django.contrib.gis.geos.MultiPolygon 被移除。

  • 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() 方法已删除。

  • 使用 User.is_authenticated()User.is_anonymous() 因为不再支持方法而不是属性。

  • 这个 Model._meta.virtual_fields 属性被删除。

  • 关键字参数 virtual_only 在里面 Field.contribute_to_class()virtual 在里面 Model._meta.add_field() 被移除。

  • 这个 javascript_catalog()json_catalog() 视图被删除。

  • django.contrib.gis.utils.precision_wkt() 被移除。

  • 在多表继承中,隐式提升 OneToOneField 到A parent_link 被移除。

  • 支持 Widget._format_value() 被移除。

  • FileField 方法 get_directory_name()get_filename() 被移除。

  • 这个 mark_for_escaping() 函数及其使用的类: EscapeDataEscapeBytesEscapeTextEscapeStringEscapeUnicode 被移除。

  • 这个 escape 过滤器现在使用 django.utils.html.conditional_escape() .

  • Manager.use_for_related_fields 被移除。

  • 模型 Manager 继承遵循MRO继承规则。使用要求 Meta.manager_inheritance_from_future 选择加入行为将被删除。

  • 支持旧式中间件使用 settings.MIDDLEWARE_CLASSES 被移除。