Django 1.7 版本发布说明:新特性与升级指南
创始人
2026-05-09 15:20:36
0

Django 1.7 版本发行说明

2014 年 9 月 2 日

欢迎使用 Django 1.7 !

这些发布说明涵盖了 新功能,以及在从 Django 1.6 或更旧版本升级时需要注意的一些 不兼容的变更。我们已经 开始了一些功能的弃用过程,并且一些功能已经完成了其弃用过程,已经 被移除

Python 兼容性

Django 1.7 需要 Python 2.7、3.2、3.3 或 3.4。我们 强烈建议 并且只官方支持每个系列的最新版本。

Django 1.6 系列是最后一个支持 Python 2.6 的版本。 Django 1.7 是第一个支持 Python 3.4 的版本。

这个改变应该只影响少数 Django 用户,因为大多数操作系统供应商现在都将 Python 2.7 或更新版本作为默认版本发布。然而,如果您仍在使用 Python 2.6,那么您需要继续使用 Django 1.6,直到您可以升级您的 Python 版本。根据 我们的支持政策,Django 1.6 将继续获得安全支持,直到 Django 1.8 发布为止。

Django 1.7 的新特性包括:

模式迁移

Django 现在内置了对模式迁移的支持。它允许通过创建迁移文件来更新、修改和删除模型,这些迁移文件代表了模型的变更,可以在任何开发、暂存或生产数据库上运行。

迁移在 自己的文档中 中有详细的介绍,但其中一些关键特性包括:

  • syncdb 已经被弃用,被 migrate 取代。不用担心 - 对 syncdb 的调用仍然会像以前一样工作。

  • 新的 makemigrations 命令提供了一种自动检测模型更改并为其创建迁移的简便方法。

    django.db.models.signals.pre_syncdbdjango.db.models.signals.post_syncdb 已经被弃用,分别由 pre_migratepost_migrate 取代。这些新信号具有稍微不同的参数。请查阅文档以获取详细信息。

  • 数据库路由器上的 allow_syncdb 方法现在被称为 allow_migrate,但仍然执行相同的功能。具有 allow_syncdb 方法的路由器仍然可以工作,但该方法名称已被弃用,您应尽快更改它(只需要重命名即可)。

  • 不再为具有迁移的应用程序加载 initial_data fixture;如果您想为应用程序加载初始数据,建议您为应用程序创建一个迁移,并在迁移的 operations 部分中定义一个 RunPythonRunSQL 操作。

  • 对于具有迁移的应用程序,测试回滚行为会有所不同;特别是,Django 不再在非事务性数据库上或 TransactionTestCase 内模拟回滚,除非明确请求(除非明确请求)。

  • 不建议没有迁移的应用程序依赖于(具有 ForeignKeyManyToManyField 的)具有迁移的应用程序。

应用加载重构

在过去,Django 应用与模型紧密耦合。一个名为 "应用缓存" 的单例处理已安装的应用和模型。许多 API 中使用模型模块作为应用的标识符。

随着 Django 应用程序 概念的成熟,这段代码显示出了一些不足之处。它已经被重构为一个 "应用程序注册表",在这里模型模块不再起到核心作用,同时可以将配置数据附加到应用程序。

迄今为止的改进包括:

  • 应用程序可以在启动时运行代码,在 Django 执行任何其他操作之前,使用其配置的 ready() 方法。

  • 即使在 models.py 之外定义模型,应用程序标签也会被正确地分配给模型。您不再需要显式设置 app_label

  • 如果一个应用程序没有任何模型,完全可以省略 models.py

  • 可以使用应用程序配置的 label 属性重新标记应用程序,以解决标签冲突。

  • 可以使用应用程序配置的 verbose_name 来自定义在管理员界面中的应用程序名称。

  • The admin automatically calls autodiscover() when Django starts. You can consequently remove this line from your URLconf.

  • Django 在启动时通过一种确定性且简单的过程导入所有应用程序配置和模型。这将使诊断导入问题(如导入循环)变得更容易。

Field 子类的新方法

为了支持模式迁移并使未来版本的 Django 更容易添加复合键,Field API 现在有一个新的必需方法:deconstruct()

该方法不接受任何参数,并返回一个包含四个元素的元组:

  • name:字段在其父模型上的属性名称,如果它不是模型的一部分,则为 None

  • path:字段类的点分隔的 Python 路径,包括类名。

  • args:作为列表的位置参数。

  • kwargs:作为字典的关键字参数。

这四个值允许将任何字段序列化到文件中,并且允许字段进行安全复制,这是这些新功能的重要组成部分。

这个变化不会影响您,除非您编写自定义的 Field 子类;如果您这样做,如果您的子类以任何方式更改了 __init__ 的方法签名,您可能需要重新实现 deconstruct() 方法。如果您的字段只是继承自内置的 Django 字段,并且没有重写 __init__,则无需进行任何更改。

如果您确实需要重写 deconstruct(),一个好的起点是内置的 Django 字段(django/db/models/fields/__init__.py),因为其中一些字段,包括 DecimalFieldDateField,已经重写了它,并展示了如何在超类上调用该方法,只需添加或删除额外的参数。

这也意味着字段的所有参数本身必须是可序列化的;要了解我们认为什么是可序列化的,以及如何使您自己的类可序列化,请阅读 迁移序列化文档

Manager 中调用自定义的 QuerySet 方法

历史上,制作可重用的模型查询的推荐方法是在自定义 Manager 类上创建方法。这种方法的问题在于,在第一次方法调用之后,您会得到一个 QuerySet 实例,无法调用其他自定义的管理器方法。

尽管没有记录,但通常可以通过创建自定义的 QuerySet 来解决这个问题,以便可以链接自定义方法;但是这个解决方案有很多缺点:

  • 自定义的 QuerySet 和其自定义方法在第一次调用 values()values_list() 后就丢失了。

  • 仍然需要编写自定义的 Manager 来返回自定义的 QuerySet 类,并且所有希望在 Manager 上使用的方法都必须被代理到 QuerySet 上。整个过程违反了 DRY 原则。

现在可以直接使用 QuerySet.as_manager() 类方法来 创建具有 QuerySet 方法的 Manager

class FoodQuerySet(models.QuerySet):
    def pizzas(self):
        return self.filter(kind="pizza")

    def vegetarian(self):
        return self.filter(vegetarian=True)

class Food(models.Model):
    kind = models.CharField(max_length=50)
    vegetarian = models.BooleanField(default=False)
    objects = FoodQuerySet.as_manager()

Food.objects.pizzas().vegetarian()

在遍历反向关系时使用自定义管理器

现在可以在遍历反向关系时 指定自定义的管理器

class Blog(models.Model):
    pass

class Entry(models.Model):
    blog = models.ForeignKey(Blog)

    objects = models.Manager()  # Default Manager
    entries = EntryManager()  # Custom Manager

b = Blog.objects.get(id=1)
b.entry_set(manager="entries").all()

新的系统检查框架

我们新增了一个新的 系统检查框架,用于检测常见问题(比如无效的模型)并提供解决这些问题的提示。这个框架是可扩展的,因此您可以为自己的应用程序和库添加自定义检查。

要执行系统检查,您可以使用 check 管理命令。这个命令替代了旧的 validate 管理命令。

新的 Prefetch 对象用于高级的 prefetch_related 操作。

新的 Prefetch 对象允许自定义预取操作。

您可以指定用于遍历特定关系的 QuerySet,或者自定义预取结果的存储位置。

This enables things like filtering prefetched relations, calling select_related() from a prefetched relation, or prefetching the same relation multiple times with different querysets. See prefetch_related() for more details.

管理快捷方式支持时区

在管理员中日期和时间输入小部件旁边的 "today" 和 "now" 快捷方式现在在 当前时区 中运行。以前,它们使用浏览器的时区,这可能导致在时区不匹配服务器的当前时区时保存错误的值。

此外,小部件现在在浏览器和服务器时区不同时显示帮助信息,以明确解释字段中插入的值将如何被解释。

使用数据库游标作为上下文管理器

在 Python 2.7 之前,数据库游标可以用作上下文管理器。具体的后端游标定义了上下文管理器的行为。但是,Python 2.7 改变了魔术方法查找的行为,游标不再能用作上下文管理器。

Django 1.7 允许将游标用作上下文管理器。也就是说,可以使用以下方式:

with connection.cursor() as c:
    c.execute(...)

替换成:

c = connection.cursor()
try:
    c.execute(...)
finally:
    c.close()

自定义查找

现在可以为 ORM 编写自定义查找和转换。自定义查找与 Django 内置的查找(例如 lteicontains)类似,而转换是一个新概念。

django.db.models.Lookup 类提供了一种为模型字段添加查找运算符的方式。例如,可以为 DateFields 添加 day_lte 运算符。

django.db.models.Transform 类允许在最终查找之前对数据库值进行转换。例如,可以编写一个 year 转换,从字段的值中提取年份。转换允许进行链式操作。在将 year 转换添加到 DateField 后,可以对转换后的值进行筛选,例如 qs.filter(author__birthdate__year__lte=1981)

有关自定义查找和转换的更多信息,请参阅 自定义查找 文档。

改进了 Form 错误处理

Form.add_error()

以前在处理表单错误方面有两种主要模式:

  • 在某些函数(例如 Field.clean()Form.clean_()Form.clean() 用于非字段错误的情况)中引发 ValidationError

  • Form.clean() 中针对特定字段或在“clean”方法之外(例如直接从视图中)添加错误时,会涉及到 Form._errors

使用前一种模式是直接的,因为表单可以根据上下文(即引发异常的方法)猜测错误的归属,并自动处理它们。这仍然是可能时添加错误的规范方式。然而,后一种模式很繁琐且容易出错,因为处理边缘情况的负担落在用户身上。

The new add_error() method allows adding errors to specific form fields from anywhere without having to worry about the details such as creating instances of django.forms.utils.ErrorList or dealing with Form.cleaned_data. This new API replaces manipulating Form._errors which now becomes a private API.

请参阅 使用 Form.add_error() 进行字段验证,以获取使用 Form.add_error() 的示例。

错误元数据

ValidationError 构造函数接受元数据,如错误 codeparams,然后可以将其插入到错误消息中(有关更多详细信息,请参阅 引发 ValidationError);然而,在 Django 1.7 之前,这些元数据在错误添加到 Form.errors 后立即被丢弃。

Form.errorsdjango.forms.utils.ErrorList 现在存储了 ValidationError 实例,因此可以通过新的 Form.errors.as_data 方法在任何时候检索这些元数据。

检索到的 ValidationError 实例可以通过其错误 code 进行标识,从而可以进行诸如重写错误消息或在特定错误存在时编写视图中的自定义逻辑等操作。它还可以用于以自定义格式(例如 XML)序列化错误。

新的 Form.errors.as_json() 方法是一个方便的方法,它返回以 JSON 格式序列化的错误消息以及错误代码。as_json() 使用了 as_data(),并展示了如何扩展新系统的思路。

错误容器和向后兼容性

为了支持上述功能,需要对各种错误容器进行重大更改,特别是 Form.errorsdjango.forms.utils.ErrorListValidationError 的内部存储。这些容器曾经存储错误字符串,现在存储 ValidationError 实例,并且公共 API 已经进行了适应,使这些更改尽可能透明,但如果您曾经使用过私有 API,一些更改可能不兼容向后;有关更多详细信息,请参阅 ValidationError 构造函数和内部存储

次要特性

django.contrib.admin

django.contrib.auth

django.contrib.formtools

  • WizardView.done() 的调用现在包括一个 form_dict,以便更容易按步骤名称访问表单。

django.contrib.gis

  • 默认包含在小部件中的 OpenLayers 库版本已从 2.11 更新为 2.13 。

  • 如果安装了 GEOS 3.3 或更高版本,预处理的几何图形现在还支持 crossesdisjointoverlapstoucheswithin 谓词。

django.contrib.messages

django.contrib.redirects

django.contrib.sessions

  • "django.contrib.sessions.backends.cached_db" 会话后端现在尊重 SESSION_CACHE_ALIAS。在之前的版本中,它总是使用 default 缓存。

django.contrib.sitemaps

django.contrib.sites

django.contrib.staticfiles

  • 可以通过子类化 静态文件存储类 来覆盖收集的静态文件和目录的权限,方法是设置 file_permissions_modedirectory_permissions_mode 参数。请参阅 collectstatic 以查看示例用法。

  • CachedStaticFilesStorage 后端有一个名为 ManifestStaticFilesStorage 的兄弟类,它根本不使用缓存系统,而是使用一个名为 staticfiles.json 的 JSON 文件来存储原始文件名(例如 css/styles.css)和散列文件名(例如 css/styles.55e7cbb9ba48.css)之间的映射关系。当运行 collectstatic 管理命令时,会创建 staticfiles.json 文件,对于 Amazon S3 等远程存储来说,这应该是一个更经济的替代方案。

    有关更多信息,请参阅 ManifestStaticFilesStorage 文档。

  • findstatic 现在接受详细程度为 2 的 verbosity 标志,这意味着它将显示搜索的目录的相对路径。请参阅 findstatic 以查看示例输出。

django.contrib.syndication

  • Atom1Feed 辅助工具中的 updated 元素现在使用 updateddate 而不是 pubdate,允许在 feed 中包含 published 元素(该元素依赖于 pubdate)。

缓存

  • 现在可以通过 django.core.cache.caches 访问在 CACHES 中配置的缓存。这个类似字典的对象为每个线程提供一个不同的实例。它取代了已被弃用的 django.core.cache.get_cache()

  • 如果直接实例化缓存后端,请注意它们不再是线程安全的,因为 django.core.cache.caches 现在为每个线程提供不同的实例。

  • CACHES 设置的 TIMEOUT 参数定义为 None 将默认将缓存键设置为 "永不过期"。以前,只能将 timeout=None 传递给缓存后端的 set() 方法。

跨站请求伪造(Cross Site Request Forgery,CSRF)

电子邮件

  • send_mail() 现在接受一个 html_message 参数,用于发送多部分 text/plaintext/html 的电子邮件。

  • SMTP EmailBackend 现在接受一个 timeout 参数。

文件存储

  • 在 Windows 上,文件锁定以前依赖于 PyWin32 软件包;如果未安装该软件包,则文件锁定会默默失败。现在已经移除了这个依赖项,文件锁定在 Windows 和 Unix 上都使用本地实现。

文件上传

  • 新的 UploadedFile.content_type_extra 属性包含在文件上传的 content-type 标头中传递的额外参数。

  • 新的 FILE_UPLOAD_DIRECTORY_PERMISSIONS 设置控制在文件上传期间创建的目录的文件系统权限,就像 FILE_UPLOAD_PERMISSIONS 一样控制文件本身的权限。

  • FileField.upload_to 属性现在是可选的。如果省略或给定 None 或空字符串,将不会使用子目录来存储上传的文件。

  • 上传的文件现在在响应交付给客户端之前明确关闭。只要在上传处理程序中的名称为 file,部分上传的文件也会被关闭。

  • Storage.get_available_name() 现在追加一个下划线加上一个随机的 7 个字符的字母数字字符串(例如,"_x3a1gho"),而不是通过一个下划线后跟一个数字(例如,"_1", "_2" 等)来进行迭代,以防止拒绝服务攻击。这个更改也在 1.6.6、1.5.9 和 1.4.14 安全发布版中进行了更改。

表单

  • RadioSelectCheckboxSelectMultiple 渲染的单选按钮或复选框的 标签现在分别包括 forid 属性。每个单选按钮或复选框都包括一个 id_for_label 属性以输出元素的 ID。

  • Textarea 渲染的