Django 1.10 版本发行说明¶
2016 年 8 月 1 日
欢迎来到 Django 1.10 版本!
这些发布说明涵盖了 新功能,以及一些 不兼容的更改,在从 Django 1.9 或更早版本升级时,您需要注意这些更改。我们已经 放弃了一些功能,它们已经达到了停用周期的末尾,同时我们已经 开始了一些功能的停用过程。
如果你要更新现有的项目,请看 如何将 Django 更新至新的版本 指南。
Python 兼容性¶
与 Django 1.9 一样,Django 1.10 需要 Python 2.7、3.4 或 3.5。我们 强烈建议 并且只正式支持每个系列的最新版本。
Django 1.10 新特性¶
PostgreSQL 的全文搜索¶
django.contrib.postgres
现在包括一个 数据库函数集合,允许使用全文搜索引擎。您可以在关系数据库中跨多个字段进行搜索,将搜索与其他查找组合使用,使用不同的语言配置和权重,以及按相关性对结果进行排名。
它还现在包括 trigram 支持,使用 trigram_similar
查找以及 TrigramSimilarity
和 TrigramDistance
表达式。
新式中间件¶
引入了一种新的中间件风格,以解决旧式中间件的请求/响应层次不严格的问题,这在 DEP 0005 中有描述。您需要 调整旧的自定义中间件,并从 MIDDLEWARE_CLASSES
设置切换到新的 MIDDLEWARE
设置以充分利用这些改进。
官方支持 Unicode 用户名¶
django.contrib.auth
中的 User
模型最初只接受用户名中的 ASCII 字母和数字。尽管这不是一个故意的选择,在使用 Python 3 时,Unicode 字符一直都被接受。
用户名验证器现在默认情况下仅在 Python 3 上明确接受 Unicode 字符。
自定义用户模型可以使用新的 ASCIIUsernameValidator
或 UnicodeUsernameValidator
。
次要特性¶
django.contrib.admin
¶
- 对于运行在子路径上的站点,每个管理页面顶部的默认
"查看站点"链接的 URL
现在将指向request.META['SCRIPT_NAME']
(如果设置了),而不是/
。 - 现在,在添加或编辑对象后出现的成功消息中包含到对象的更改表单的链接。
- 所有内联 JavaScript 都已移除,因此您可以启用
Content-Security-Policy
HTTP 标头(如果需要的话)。 - 新的
InlineModelAdmin.classes
属性允许在内联字段集上指定类。具有collapse
类的内联将初始折叠,并且它们的标题将有一个小的 "显示" 链接。 - 如果用户没有添加权限,模型的更改列表上的
object-tools
区块现在将被呈现(没有添加按钮)。这在这种情况下更容易添加自定义工具。 LogEntry
模型现在将更改消息存储在 JSON 结构中,以便可以使用当前活动的语言动态翻译消息。现在,首选的检索更改消息的方式是使用新的LogEntry.get_change_message()
方法。- 在
ModelAdmin.raw_id_fields
中选定的字段的对象现在具有指向对象的更改表单的链接。 - 如果字段可为空,为
DateFieldListFilter
添加了 "无日期" 和 "有日期" 选项。 - 管理后台中嵌入的 jQuery 库已经从 2.1.4 版本升级到 2.2.3 版本。
django.contrib.auth
¶
- 增加了对 Argon2 密码哈希 的支持。它被推荐用于替代 PBKDF2,但不是默认选项,因为它需要一个第三方库。
- PBKDF2 密码哈希的默认迭代次数已增加 25%。这个向后兼容的更改不会影响那些已经子类化了
django.contrib.auth.hashers.PBKDF2PasswordHasher
以更改默认值的用户。 django.contrib.auth.views.logout()
视图发送 "no-cache" 标头,以防止 Safari 缓存重定向并阻止用户注销的问题。- 新增了可选的
backend
参数以供django.contrib.auth.login()
使用,允许在没有凭据的情况下使用它。 - 新的
LOGOUT_REDIRECT_URL
设置控制了django.contrib.auth.views.logout()
视图的重定向,如果视图没有得到一个next_page
参数。 - 新的
redirect_authenticated_user
参数用于django.contrib.auth.views.login()
视图,允许重定向已经经过身份验证的用户访问登录页面。 - 新的
AllowAllUsersModelBackend
和AllowAllUsersRemoteUserBackend
忽略了User.is_active
的值,而ModelBackend
和RemoteUserBackend
现在拒绝不活动的用户。
django.contrib.gis
¶
- 距离查找 现在接受表达式作为距离值参数。
- 新的
GEOSGeometry.unary_union
属性计算了此几何对象的所有元素的并集。 - 新增了
GEOSGeometry.covers()
二元谓词。 - 新增了
GDALBand.statistics()
方法以及mean
和std
属性。 - 在 SpatiaLite 上新增了对
MakeLine
聚合和GeoHash
函数的支持。 - 在 MySQL 上新增了对
Difference
、Intersection
和SymDifference
函数的支持。 - 新增支持实例化空的 GEOS 几何对象。
WKTWriter
的新属性trim
和precision
允许控制 WKT 中坐标的小数部分的输出。- 新增了
LineString.closed
和MultiLineString.closed
属性。 - 如果没有指定特定字段, GeoJSON 序列化程序 现在会在
properties
字典中输出对象的主键。 - 现在可以在
GDALBand.data()
方法上复制输入数据。可以高效地使用重复的值更新带数据。 - 新增了数据库函数
IsValid
和MakeValid
,以及isvalid
查找,都用于 PostGIS。这允许在数据库端对无效的几何对象进行过滤和修复。 - 新增了所有 空间查找 的栅格支持。
django.contrib.postgres
¶
- 为了方便起见,
HStoreField
现在将其键和值转换为字符串。
django.contrib.sessions
¶
clearsessions
管理命令现在会删除基于文件的会话。
缓存¶
- 基于文件的缓存后端现在使用最高的 pickling 协议。
CSRF¶
- 默认的
CSRF_FAILURE_VIEW
,views.csrf.csrf_failure()
现在接受一个可选的template_name
参数,默认为'403_csrf.html'
,用于控制渲染页面的模板。 - 为了防止 BREACH 攻击,CSRF 保护机制现在会在每个请求中更改表单令牌的值(同时保持不变的秘密,可用于验证不同的令牌)。
数据库后端¶
- 临时数据减法在所有后端上得到了统一。
- 如果数据库支持,后端可以设置
DatabaseFeatures.can_return_ids_from_bulk_insert=True
并实现DatabaseOperations.fetch_returned_insert_ids()
,以便在使用QuerySet.bulk_create()
创建的对象上设置主键。 - 为各种表达式(
Func
、When
、Case
和OrderBy
)的as_sql()
方法添加了关键字参数,允许数据库后端在不更改self
的情况下自定义它们,这在使用不同的数据库后端时不安全。参见Func.as_sql()
的arg_joiner
和**extra_context
参数的示例。
文件存储¶
- 存储后端现在提供一个时区感知的 API,具有新的方法
get_accessed_time()
、get_created_time()
和get_modified_time()
。如果USE_TZ
为True
,则它们返回一个时区感知的datetime
,否则返回本地时区的非时区感知的datetime
。 - 新的
Storage.generate_filename()
方法使得更容易实现不使用以前在FileField
中的os.path
调用的自定义存储。
表单¶
- 如果安装了
django.contrib.staticfiles
,则现在会使用它来提供表单和小部件的Media
。 - 由
CharField
渲染的<input>
标签现在如果字段具有min_length
,则会包含一个minlength
属性。 - 现在,必填表单字段具有
required
HTML 属性。将新的Form.use_required_attribute
属性设置为False
可以禁用它。在表单集的表单上不包括required
属性,因为在添加和删除表单集时,浏览器验证可能不正确。
国际化¶
i18n_patterns()
辅助函数现在可以在使用request.urlconf
指定的根 URL 配置中使用。- 通过将
i18n_patterns()
的新参数prefix_default_language
设置为False
,您可以允许在没有 URL 前缀的情况下访问默认语言。 - 现在,当在
POST
或GET
中没有next
参数时,set_language()
对于 AJAX 请求会返回 204 状态码(No Content)。 JavaScriptCatalog
和JSONCatalog
类视图取代了不推荐使用的javascript_catalog()
和json_catalog()
函数视图。新视图与旧视图几乎相同,唯一的区别是,默认情况下,新视图会从所有已安装的应用程序中收集djangojs
翻译域中的所有 JavaScript 字符串,而不仅仅是来自LOCALE_PATHS
的 JavaScript 字符串。
管理命令¶
- 现在,
call_command()
会返回从command.handle()
方法返回的值。 - 新的
check --fail-level
选项允许指定消息级别,该级别将导致命令以非零状态退出。 - 新的
makemigrations --check
选项在检测到模型更改而没有迁移时,使命令以非零状态退出。 makemigrations
现在会显示生成的迁移文件的路径。shell --interface
选项现在接受python
,以强制使用 "plain" Python 解释器。- 新的
shell --command
选项允许您以 Django 用户身份运行命令并退出,而不是打开交互式 shell。 - 如果指定了代理模型(导致没有输出)而没有指定其具体的父模型,
dumpdata
现在会显示警告。 - 新的
BaseCommand.requires_migrations_checks
属性可以设置为True
,如果您希望您的命令在磁盘上的迁移集与数据库中的迁移不匹配时打印警告,就像runserver
一样。 - 为了辅助测试,
call_command()
现在接受一个命令对象作为第一个参数。 shell
命令在使用libedit
的系统上支持制表符自动完成,例如 macOS。inspectdb
命令允许您通过将表的名称指定为参数来选择应该进行检查的表。
迁移¶
- 新增支持序列化
enum.Enum
对象。 - 在
RunSQL
和RunPython
操作中添加了elidable
参数,以允许在压缩迁移时删除它们。 - 通过在
Migration
上设置atomic
属性,添加了对 非原子迁移 的支持。 migrate
和makemigrations
命令现在会 检查一致的迁移历史。如果它们发现某些已应用的迁移存在未应用的依赖项,将会引发InconsistentMigrationHistory
异常。pre_migrate()
和post_migrate()
信号现在会分发它们的迁移plan
和apps
。
模型¶
- 来自代理模型的反向外键现在会传播到它们的具体类。指向代理模型的
ForeignKey
所附加的反向关系现在可以作为描述符在代理模型类上访问,并且可以在查询集过滤中引用。 - 新的
Field.rel_db_type()
方法返回了诸如ForeignKey
和OneToOneField
这样指向另一个字段的字段的数据库列数据类型。 Func
添加了arity
类属性。此属性可用于设置函数接受的参数数量。- 新增了
BigAutoField
,它的行为类似于AutoField
,但它保证适合于范围从1
到9223372036854775807
的数字。 - 可以不带任何参数调用
QuerySet.in_bulk()
,以返回查询集中的所有对象。 related_query_name
现在支持使用'%(app_label)s'
和'%(class)s'
字符串进行应用标签和类的插值。- 允许覆盖从抽象基类继承的模型字段。
prefetch_related_objects()
函数现在是一个公共 API。QuerySet.bulk_create()
在使用 PostgreSQL 时会设置对象的主键。- 新增了
Cast
数据库函数。 - 现在,代理模型可以继承多个共享非抽象父类的代理模型。
- 新增了
Extract
函数,用于提取日期时间组件作为整数,例如年份和小时。 - 新增了
Trunc
函数,用于将日期或日期时间截断到一个重要的组件。它们使得可以执行类似每天销售或每小时销售的查询。 Model.__init__()
现在会从关键字参数中设置虚拟字段的值。- 新的
Meta.base_manager_name
和Meta.default_manager_name
选项允许分别控制_base_manager
和_default_manager
。
请求和响应¶
- 在调试视图中添加了
request.user
。 - 添加了
HttpResponse
的方法readable()
和seekable()
,以使实例成为类似流的对象,并允许将其包装在io.TextIOWrapper
中。 - 添加了
HttpRequest.content_type
和content_params
属性,这些属性从CONTENT_TYPE
标头中解析而来。 request.COOKIES
的解析器被简化,以更好地匹配浏览器的行为。request.COOKIES
现在可以包含根据 RFC 6265 无效但可以通过document.cookie
设置的 cookie。
序列化¶
django.core.serializers.json.DjangoJSONEncoder
现在知道如何序列化懒惰字符串,通常用于可翻译的内容。
模板¶
测试¶
- 为了更好地捕获错误,
TestCase
现在在每个测试结束时检查可延迟的数据库约束。 - 测试和测试用例可以被 标记为标签 并可以使用新的
test --tag
和test --exclude-tag
选项进行选择性运行。 - 即使
django.contrib.sessions
不在INSTALLED_APPS
中,您现在也可以使用测试客户端登录并使用会话。
URLs¶
- 在
django.setup()
中的一个新添加允许在请求/响应周期之外发生的 URL 解析(例如在管理命令和独立脚本中)在设置FORCE_SCRIPT_NAME
时考虑到它。
验证器¶
URLValidator
现在将域名标签的长度限制为 63 个字符,域名的总长度限制为 253 个字符,符合 RFC 1034 的规定。int_list_validator()
现在接受一个可选的布尔参数allow_negative
,默认为False
,以允许负整数。
1.10 中的不向后兼容的变更¶
警告
除了本节中概述的更改之外,请务必查看 在 1.10 中移除的功能,了解已经到达了弃用周期终点并因此被移除的功能。如果您没有在给定功能的弃用时间表内更新您的代码,它的移除可能会被视为不兼容的更改。
数据库后端 API¶
- GIS 的
AreaField
使用一个未指定的底层数字类型,实际上可以是任何 Python 数值类型。从数据库中检索到的decimal.Decimal
值现在被转换为float
,以便更容易将它们与 GIS 库使用的值结合在一起。 - 为了启用时间减法,您必须将数据库功能标志
supports_temporal_subtraction
设置为True
,并实现DatabaseOperations.subtract_temporals()
方法。该方法应返回计算``lhs`` 和rhs
参数之间差异的微秒数所需的 SQL 和参数,其数据类型用于存储DurationField
。
_meta.get_fields()
为代理模型返回一致的反向字段。¶
在 Django 1.10 之前,当在代理模型上调用 get_fields()
方法时,返回的反向字段与其代理的具体类相比是不同的。这种不一致性已经通过在两种情况下都返回指向具体类或其代理之一的字段的完整集合来修复。
AbstractUser.username
的 max_length
增加到了 150。¶
包括了一个针对 django.contrib.auth.models.User.username
的迁移。如果您有一个继承自 AbstractUser
的自定义用户模型,您需要为您的用户模型生成并应用一个数据库迁移。
我们考虑将用户名的最大长度增加到 254 个字符,以更容易允许使用电子邮件地址(限制为 254 个字符)作为用户名,但由于 MySQL 的限制而拒绝了这个提案。当使用 utf8mb4
编码(推荐用于正确支持 Unicode)时,默认情况下,MySQL 只能创建包含 191 个字符的唯一索引。因此,如果您需要更长的长度,请使用自定义用户模型。
如果您想保留用户名的 30 个字符限制,请在创建用户或更改用户名时使用自定义表单:
from django.contrib.auth.forms import UserCreationForm
class MyUserCreationForm(UserCreationForm):
username = forms.CharField(
max_length=30,
help_text="Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.",
)
如果您希望在管理员中保留这个限制,可以将 UserAdmin.add_form
设置为使用以下表单:
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
class UserAdmin(BaseUserAdmin):
add_form = MyUserCreationForm
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
停止支持 PostgreSQL 9.1¶
PostgreSQL 9.1 的上游支持将在 2016 年 9 月结束。因此,Django 1.10 将 PostgreSQL 9.2 设置为其正式支持的最低版本。
runserver
输出经过日志记录¶
runserver
命令的请求和响应处理发送到 django.server 日志记录器,而不是发送到 sys.stderr
。如果您禁用了 Django 的日志配置或使用自己的配置覆盖了它,如果您想看到该输出,您需要添加适当的日志配置:
LOGGING = {
# ...
"formatters": {
"django.server": {
"()": "django.utils.log.ServerFormatter",
"format": "[%(server_time)s] %(message)s",
}
},
"handlers": {
"django.server": {
"level": "INFO",
"class": "logging.StreamHandler",
"formatter": "django.server",
},
},
"loggers": {
"django.server": {
"handlers": ["django.server"],
"level": "INFO",
"propagate": False,
}
},
}
auth.CustomUser
和 auth.ExtensionUser
测试模型已被移除。¶
自 Django 1.8 开始为 contrib 应用程序引入迁移以来,这些自定义用户测试模型的表不再创建,使它们无法在测试环境中使用。
在 Django 之外反序列化模型时,应用程序注册表不再自动填充。¶
在反序列化模型时,不再自动填充应用程序注册表。这在 Django 1.7.2 中添加,是为了允许在 Django 之外反序列化模型,比如在 RQ worker 中,而不需要调用 django.setup()
,但这会导致死锁的可能性。在 RQ 的情况下,为了适应您的代码,您可以 提供自己的工作脚本,其中调用 django.setup()
。
删除了非空外键字段的空值赋值检查。¶
在旧版本中,将 None
分配给非空 ForeignKey
或 OneToOneField
会引发 ValueError('Cannot assign None: "model.field" does not allow null values.')
。为了与没有类似检查的其他模型字段保持一致,此检查已被移除。
从默认的 PASSWORD_HASHERS
设置中移除了弱密码哈希器。¶
Django 0.90 将密码存储为未加盐的 MD5 。 Django 0.91 添加了对加盐 SHA1 的支持,并在用户登录时自动升级密码。 Django 1.4 将 PBKDF2 作为默认密码哈希器。
如果您有一个旧的 Django 项目,其中包含使用 MD5 或 SHA1(即使使用了盐值)编码的密码,请注意,这些密码可以在今天的硬件上相对容易地被破解。为了让 Django 用户确认继续使用弱哈希器,以下哈希器已从默认的 PASSWORD_HASHERS
设置中移除:
"django.contrib.auth.hashers.SHA1PasswordHasher"
"django.contrib.auth.hashers.MD5PasswordHasher"
"django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher"
"django.contrib.auth.hashers.UnsaltedMD5PasswordHasher"
"django.contrib.auth.hashers.CryptPasswordHasher"
考虑使用一个 包装的密码哈希器 来加强数据库中的哈希值。如果这不可行,可以将 PASSWORD_HASHERS
设置添加到您的项目中,并添加回您需要的任何哈希器。
您可以像这样检查您的数据库是否具有任何已删除的哈希器:
from django.contrib.auth import get_user_model
User = get_user_model()
# Unsalted MD5/SHA1:
User.objects.filter(password__startswith="md5$$")
User.objects.filter(password__startswith="sha1$$")
# Salted MD5/SHA1:
User.objects.filter(password__startswith="md5$").exclude(password__startswith="md5$$")
User.objects.filter(password__startswith="sha1$").exclude(password__startswith="sha1$$")
# Crypt hasher:
User.objects.filter(password__startswith="crypt$$")
from django.db.models import CharField
from django.db.models.functions import Length
CharField.register_lookup(Length)
# Unsalted MD5 passwords might not have an 'md5$$' prefix:
User.objects.filter(password__length=32)
Field.get_prep_lookup()
和 Field.get_db_prep_lookup()
方法已被移除。¶
如果您有一个自定义字段实现了这两种方法中的任何一种,请为其注册一个自定义查找。例如:
from django.db.models import Field
from django.db.models.lookups import Exact
class MyField(Field): ...
class MyFieldExact(Exact):
def get_prep_lookup(self):
# do_custom_stuff_for_myfield
...
MyField.register_lookup(MyFieldExact)
django.contrib.gis
¶
- 不再支持 SpatiaLite < 3.0 和 GEOS < 3.3 。
add_postgis_srs()
的向后兼容别名已被移除,应使用django.contrib.gis.utils.add_srs_entry()
。- 在 Oracle/GIS 上,
Area
聚合函数现在返回一个float
,而不再是decimal.Decimal
。(它仍然以平方米为单位包装。) - 默认情况下,
GEOSGeometry
的表示形式(WKT 输出)现在默认被修剪。也就是说,不再是POINT (23.0000000000000000 5.5000000000000000)
,而是POINT (23 5.5)
。
请求体的最大大小以及 GET/POST 参数的数量受到限制。¶
两个新配置有助于减轻通过大型请求发起的拒绝服务攻击:
DATA_UPLOAD_MAX_MEMORY_SIZE
限制请求主体的大小。文件上传不计入此限制。DATA_UPLOAD_MAX_NUMBER_FIELDS
限制解析的 GET/POST 参数的数量。
接收异常大表单提交的应用程序可能需要调整这些设置。
杂项¶
QuerySet
的repr()
现在在调试时会包装在<QuerySet >
中,以便与普通列表进行区分。utils.version.get_version()
返回符合 PEP 440 的候选版本(例如 '1.10rc1' 而不是 '1.10c1')。- 现在要求 CSRF 令牌值必须是 64 个字母数字字符串;默认情况下,由旧版 Django 设置的 32 个字母数字值将自动替换为 64 个字符的字符串。其他值将被视为无效。这应该只会影响替换这些令牌的开发人员或用户。
LOGOUT_URL
设置已删除,因为自 1.0 版本以来 Django 不再使用它。如果你在项目中使用了它,可以将其添加到项目的设置中。默认值是'/accounts/logout/'
。- 具有
close()
方法的对象,例如文件和生成器,传递给HttpResponse
现在会立即关闭,而不是在 WSGI 服务器调用响应的close()
方法时关闭。 - 在
QuerySet.update_or_create()
中删除了多余的transaction.atomic()
调用。这可能会影响TransactionTestCase.assertNumQueries()
测试的查询计数。 - 在
BaseCommand.execute(**options)
中删除了对skip_validation
的支持。请改用skip_checks
(Django 1.7 中添加)来代替。 - 现在,在指定的夹具文件未找到时,
loaddata
将引发一个CommandError
,而不是显示警告。 - 现在,最好调用
LogEntry.get_change_message()
方法来获取日志条目的消息,而不是直接访问LogEntry.change_message
属性,这样可以提供当前语言的消息。 - 如果指定了不存在的
template_name
,默认错误视图现在会引发TemplateDoesNotExist
异常。 Select
和SelectMultiple
小部件的render()
方法中未使用的choices
关键字参数已被移除。render_options()
方法中的choices
参数也已被移除,现在selected_choices
是第一个参数。- 现在,在支持可延迟约束的数据库上运行的违反可延迟数据库约束的测试将会出现错误。
- 内置管理命令现在使用
options
中键的索引,例如options['verbosity']
,而不是options.get()
,并且不再执行任何类型强制转换。如果你正在使用Command.execute()
调用命令(绕过设置默认值的参数解析器),而不是call_command()
,这可能会导致问题。不要调用Command.execute()
,而是将命令对象作为第一个参数传递给call_command()
。 ModelBackend
和RemoteUserBackend
现在会拒绝不活跃的用户。这意味着不活跃的用户无法登录,如果将他们从is_active=True
更改为False
,他们将被登出。如果需要以前的行为,请在AUTHENTICATION_BACKENDS
中使用新的AllowAllUsersModelBackend
或AllowAllUsersRemoteUserBackend
。- 鉴于先前的更改,测试客户端的
login()
方法不再始终拒绝不活跃的用户,而是将这个决定委托给身份验证后端。force_login()
也将决定委托给身份验证后端,因此如果你使用默认的后端,你需要使用一个活跃的用户。 django.views.i18n.set_language()
现在可以为 AJAX 请求返回一个 204 状态码。RangeField
的base_field
属性现在是一个字段类型,而不是字段的实例。如果你创建了RangeField
的自定义子类,你应该更改base_field
属性。- 现在,中间件类在服务器启动时初始化,而不是在第一个请求期间。
- 如果你在自定义用户模型中重写了
is_authenticated()
或is_anonymous()
方法,你必须将它们转换为属性或属性,如 弃用说明 中所述。 - 当使用
ModelAdmin.save_as=True
时,"Save as new" 按钮现在会重定向到新对象的修改视图,而不是模型的变更列表。如果你需要之前的行为,请将新的ModelAdmin.save_as_continue
属性设置为False
。 - 必填的表单字段现在具有
required
HTML 属性。如果要禁用它,请将Form.use_required_attribute
属性设置为False
。如果不想要浏览器验证,还可以在<form>
中添加novalidate
属性。如果要在自定义小部件上禁用required
属性,请重写Widget.use_required_attribute()
方法。 - WSGI 处理程序不再从
HEAD
请求或具有status_code
为 100-199、204 或 304 的响应中删除内容。大多数 Web 服务器已经实现了这种行为。使用 Django 测试客户端检索的响应仍然会应用这些 "响应修复"。 Model.__init__()
现在会将django.db.models.DEFERRED
作为延迟字段的值。Model._deferred
属性在使用QuerySet.defer()
和only()
时动态模型类被移除。Storage.save()
不再将'\'
替换为'/'
。这个行为已经移到FileSystemStorage
中,因为这是一个与存储相关的具体实现细节。如果有自定义存储实现依赖这个行为的 Windows 用户,需要在自定义存储的save()
方法中实现这个行为。- 私有的
FileField
方法get_directory_name()
和get_filename()
不再被调用(并且现在已被弃用),这对于在自定义字段上重写这些方法的用户来说是一个不兼容的变更。要适应这种代码,可以重写FileField.generate_filename()
或Storage.generate_filename()
。也可能可以使用upload_to
。 - 由
AdminEmailHandler
发送的邮件主题不再在 989 个字符处截断。如果你依赖于有限的长度,请自行截断主题。 - 私有表达式
django.db.models.expressions.Date
和DateTime
已被移除。新的Trunc
表达式提供了相同的功能。 - 模型实例中的
_base_manager
和_default_manager
属性已被移除。您仍然可以在模型类上访问它们。 - 在模型实例上访问已删除的字段(例如,在执行
del obj.field
后)将重新加载字段的值,而不会引发AttributeError
。 - 如果您子类化了
AbstractBaseUser
并覆盖了clean()
方法,请确保在其中调用super()
。现在在新的AbstractBaseUser.clean()
方法中调用了AbstractBaseUser.normalize_username()
。 - 私有 API
django.forms.models.model_to_dict()
现在返回一个查询集而不是ManyToManyField
的主键列表。 - 如果安装了
django.contrib.staticfiles
,那么static
模板标签将使用staticfiles
存储来构建 URL,而不仅仅是与STATIC_ROOT
连接。这种新方法对URL进行了编码,可能在包含路径中的片段的情况下存在向后不兼容性,例如{% static 'img.svg#fragment' %}
,因为#
被编码为%23
。要进行适应,将片段移到模板标签之外:{% static 'img.svg' %}#fragment
。 - 当
USE_L10N
为True
时,如果没有指定格式字符串,则date
和time
过滤器现在会应用本地化。它们将使用活动区域设置中的DATE_FORMAT
和TIME_FORMAT
指示符,而不是同名的设置。
在 1.10 中被废弃的功能¶
直接分配给反向外键或多对多关系¶
不要使用直接分配来分配相关对象:
>>> new_list = [obj1, obj2, obj3]
>>> e.related_set = new_list
使用 Django 1.9 中添加的 set()
方法:
>>> e.related_set.set([obj1, obj2, obj3])
这可以避免因隐式保存导致的分配混淆。
非时区感知的 Storage
API¶
旧的、非时区感知的方法 accessed_time()
, created_time()
, 和 modified_time()
已被弃用,推荐使用新的 get_*_time()
方法。
第三方存储后端应该实现新的方法并将旧的方法标记为弃用。在此之前,基础的 Storage
类上的新的 get_*_time()
方法将根据需要将来自旧方法的 datetime
转换并在这样做时发出弃用警告。
只要第三方存储后端希望支持早期版本的 Django,它们就可以保留旧方法。
django.contrib.gis
¶
GEOSGeometry
的get_srid()
和set_srid()
方法已被弃用,推荐使用srid
属性。Point
的get_x()
,set_x()
,get_y()
,set_y()
,get_z()
, 和set_z()
方法已被弃用,推荐使用x
,y
, 和z
属性。Point
的get_coords()
和set_coords()
方法已被弃用,推荐使用tuple
属性。MultiPolygon
的cascaded_union
属性已被弃用,推荐使用unary_union
属性。django.contrib.gis.utils.precision_wkt()
函数已被弃用,推荐使用WKTWriter
。
CommaSeparatedIntegerField
模型字段¶
CommaSeparatedIntegerField
已被弃用,推荐使用 CharField
并配合 validate_comma_separated_integer_list()
验证器使用:
from django.core.validators import validate_comma_separated_integer_list
from django.db import models
class MyModel(models.Model):
numbers = models.CharField(..., validators=[validate_comma_separated_integer_list])
如果您使用的是 Oracle 数据库,CharField
使用不同的数据库字段类型(NVARCHAR2
)而不是 CommaSeparatedIntegerField
(VARCHAR2
)。根据您的数据库设置,这可能意味着相同内容的不同编码,从而导致相同内容的不同字节长度。如果您存储的值长于 NVARCHAR2
的 4000 字节限制,您应该改用 TextField
(NCLOB
)。在这种情况下,如果您有任何按字段分组的查询(例如,使用聚合注释模型或使用 distinct()
),您需要更改它们(以延迟字段)。
__search
查询查找¶
search
查询查找已被弃用,它仅支持 MySQL,并且功能非常有限。请将其替换为自定义查询查找:
from django.db import models
class Search(models.Lookup):
lookup_name = "search"
def as_mysql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return "MATCH (%s) AGAINST (%s IN BOOLEAN MODE)" % (lhs, rhs), params
models.CharField.register_lookup(Search)
models.TextField.register_lookup(Search)
使用 User.is_authenticated()
和 User.is_anonymous()
作为方法。¶
AbstractBaseUser
和 AnonymousUser
类的 is_authenticated()
和 is_anonymous()
方法现在已经变成属性。它们在 Django 2.0 之前仍然作为方法使用,但在 Django 中的所有用法现在都使用属性访问。
例如,如果您使用 AuthenticationMiddleware
并想知道用户当前是否已登录,您可以使用以下方式:
if request.user.is_authenticated:
... # Do something for logged-in users.
else:
... # Do something for anonymous users.
而不是 request.user.is_authenticated()
。
此更改可以避免在您忘记调用方法时意外泄露信息,例如:
if request.user.is_authenticated:
return sensitive_information
如果你在自定义用户模型中重写了这些方法,你必须将它们更改为属性或特性。
Django 使用一个 CallableBool
对象,以使这些属性同时可以作为属性和方法工作。因此,在弃用期结束之前,您不能使用 is
运算符比较这些属性。也就是说,以下操作不起作用:
if request.user.is_authenticated is True:
...
django.utils.safestring
的 "escape" 部分¶
mark_for_escaping()
函数以及它使用的类:EscapeData
、EscapeBytes
、EscapeText
、EscapeString
和 EscapeUnicode
已被弃用。
因此,escape
过滤器的 "懒惰" 行为(无论在过滤器链的哪个位置,它始终作为最后一个过滤器应用)已被弃用。在 Django 2.0 中,该过滤器将立即应用 conditional_escape()
。
杂项¶
makemigrations --exit
选项已被弃用,推荐使用makemigrations --check
选项。django.utils.functional.allow_lazy()
已被弃用,推荐使用新的keep_lazy()
函数,它可以使用更自然的装饰器语法。shell --plain
选项已被弃用,推荐使用-i python
或--interface python
。- 从
django.core.urlresolvers
模块导入已被弃用,推荐使用其新位置django.urls
。 - 模板中的
Context.has_key()
方法已被弃用,推荐使用in
。 Model._meta
的私有属性virtual_fields
已被弃用,推荐使用private_fields
。Field.contribute_to_class()
中的私有关键字参数virtual_only
和Model._meta.add_field()
中的virtual
已被弃用,分别推荐使用private_only
和private
。javascript_catalog()
和json_catalog()
视图已被弃用,推荐使用基于类的视图JavaScriptCatalog
和JSONCatalog
。- 在多表继承中,将一个
OneToOneField
隐式提升为parent_link
已被弃用。应该在这些字段上添加parent_link=True
。 - 私有 API
Widget._format_value()
已被公开,并重命名为format_value()
。旧名称将在弃用期间继续工作。 - 私有的
FileField
方法get_directory_name()
和get_filename()
已被弃用,推荐在Storage.generate_filename()
中执行这项工作。 - 使用
settings.MIDDLEWARE_CLASSES
的旧式中间件已被弃用。请 适应旧的自定义中间件 并使用新的MIDDLEWARE
设置。
在 1.10 中移除的功能¶
这些功能已经完成了弃用周期,并在 Django 1.10 中被移除。有关详细信息,包括如何移除这些功能的用法,请参阅 在 1.8 中被废弃的功能。
- 不再支持直接调用
SQLCompiler
作为调用其quote_name_unless_alias
方法的别名。 cycle
和firstof
模板标签已从future
模板标签库中移除。django.conf.urls.patterns()
已被移除。- 不再支持
prefix
参数用于django.conf.urls.i18n.i18n_patterns()
。 SimpleTestCase.urls
已被移除。- 在模板标签
for
中使用不正确数量的解包值将引发异常,而不是默默失败。 - 使用点分隔的 Python 路径反向
reverse()
URL 的能力已被移除。 - 使用点分隔的 Python 路径设置
LOGIN_URL
和LOGIN_REDIRECT_URL
的能力已被移除。 - 自定义管理命令不再支持
optparse
。 - 类
django.core.management.NoArgsCommand
已被移除。 django.core.context_processors
模块已被移除。django.db.models.sql.aggregates
模块已被移除。django.contrib.gis.db.models.sql.aggregates
模块已被移除。- 以下
django.db.sql.query.Query
的方法和属性已被移除:- 属性:
aggregates
和aggregate_select
将被移除。 - 方法:
add_aggregate
、set_aggregate_mask
和append_aggregate_mask
将被移除。
- 属性:
django.template.resolve_variable
已被移除。- 以下私有 API 已从
django.db.models.options.Options
(Model._meta
)中移除:get_field_by_name()
get_all_field_names()
get_fields_with_model()
get_concrete_fields_with_model()
get_m2m_with_model()
get_all_related_objects()
get_all_related_objects_with_model()
get_all_related_many_to_many_objects()
get_all_related_m2m_objects_with_model()
django.forms.RegexField
的error_message
参数已被移除。unordered_list
过滤器不再支持旧式列表。- 不再支持将字符串
view
参数传递给url()
。 - 将
django.forms.Form._has_changed()
重命名为has_changed()
的向后兼容性修补程序已被移除。 removetags
模板过滤器已被移除。django.utils.html
中的remove_tags()
和strip_entities()
函数已被移除。django.contrib.auth.views.password_reset()
中的is_admin_site
参数已被移除。django.db.models.field.subclassing.SubfieldBase
已被移除。django.utils.checksums
已被移除。django.contrib.admin.helpers.InlineAdminForm
上的original_content_type_id
属性已被移除。- 允许不为其
form_class
参数定义默认值的FormMixin.get_form()
的向后兼容性修复已被移除。 - 以下设置已被移除,您必须升级到
TEMPLATES
设置:ALLOWED_INCLUDE_ROOTS
TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_DEBUG
TEMPLATE_DIRS
TEMPLATE_LOADERS
TEMPLATE_STRING_IF_INVALID
- 向后兼容的别名
django.template.loader.BaseLoader
已被移除。 - 由
get_template()
和select_template()
返回的 Django 模板对象不再在其render()
方法中接受Context
。 - Template response APIs 强制使用
dict
和依赖后端的模板对象,而不再使用Context
和Template
。 - 以下函数和类的
current_app
参数已被移除:django.shortcuts.render()
django.template.Context()
django.template.RequestContext()
django.template.response.TemplateResponse()
- 以下函数的
dictionary
和context_instance
参数已被移除:django.shortcuts.render()
django.shortcuts.render_to_response()
django.template.loader.render_to_string()
- 以下函数的
dirs
参数已被移除:django.template.loader.get_template()
django.template.loader.select_template()
django.shortcuts.render()
django.shortcuts.render_to_response()
- 会话验证现在已启用,无论是否在
MIDDLEWARE_CLASSES
中包含'django.contrib.auth.middleware.SessionAuthenticationMiddleware'
。SessionAuthenticationMiddleware
不再有任何用途,可以从MIDDLEWARE_CLASSES
中删除。为了方便那些没有阅读此说明的用户,它被保留为一个存根,直到 Django 2.0。 - 私有属性
django.db.models.Field.related
已被移除。 migrate
管理命令的--list
选项已被移除。ssi
模板标签已被移除。- 不再支持
if
模板标签中的=
比较运算符。 - 允许在不带
max_length
参数的情况下定义Storage.get_available_name()
和Storage.save()
的向后兼容性修复已被移除。 - 在
ModelFormMixin.success_url
中移除了对旧式%(<foo>)s
语法的支持。 - 移除了``GeoQuerySet`` 聚合方法
collect()
,extent()
,extent3d()
,make_line()
, 和unionagg()
。 - 在创建内容类型实例时不再支持指定
ContentType.name
的能力。 - 不再支持旧的
allow_migrate
签名。 - 移除了使用逗号分隔参数的
{% cycle %}
语法的支持。 Signer
在提供无效的分隔符时发出的警告现在是一个ValueError
。