Django 1.2 版本发行说明
2017 年 5 月 17 日
欢迎来到 Django 1.2 版本!
经过近一年的努力,Django 1.2 收录了令人印象深刻的一系列 新特性 和大量的错误修复。这些发布说明涵盖了新特性,以及在从 Django 1.1 或更早版本升级时需要注意的重要更改。
概况
Django 1.2 引入了几个重要的大型新功能,包括:
- 在单个 Django 实例中支持 多个数据库连接。
- 模型验证 受到了 Django 的表单验证的启发。
- 极大地 改进了跨站点请求伪造 (CSRF) 的保护机制。
- 一个新的支持匿名和已验证用户的 cookie 和会话消息的 用户“消息”框架。
- 对象级权限、匿名用户的权限 和 更灵活的用户名要求 的挂钩。
- 通过 电子邮件后端 自定义电子邮件发送。
- 新的 “智能” if 模板标签 支持比较运算符。
这仅仅是亮点;完整的细节和功能列表 可能在下面找到。
参见
Django Advent 用一系列的文章和教程详细介绍了 Django 1.2 版本的发布以及其中一些新功能。
尽可能地,这些功能都是按照 我们的 API 稳定性政策 来引入的,以保持向后兼容性。
然而,有一些功能以某种方式发生了变化,对某些用户来说将不向后兼容。主要的变化包括:
已取消对 Python 2.3 的支持。请参阅下面的详细说明。
新的 CSRF 保护框架与旧系统不向后兼容。在 Django 1.4 中移除旧系统之前,旧系统的用户不会受到影响。
然而,升级到新的 CSRF 保护框架需要进行一些重要的不向后兼容的更改,详细信息请参见下面的 CSRF 保护。
自定义 Field 子类的作者应该注意,一些方法的原型发生了变化,详细信息请参见下面的 Field 上的 get_db_prep_*() 方法。
模板标签的内部发生了一些变化;需要存储状态的自定义模板标签的作者(例如,自定义控制流标签)应确保他们的代码遵循了新的 有状态模板标签 的规则。
来自 django.contrib.auth 的 user_passes_test()、login_required() 和 permission_required() 装饰器仅适用于函数,不再适用于方法。有一个简单的一行修复方法,详细信息请参见下面的 详细说明。
再次强调,这些只是会影响大多数用户的主要功能。从以前版本的 Django 升级的用户强烈建议查看完整的 不向后兼容的更改列表 和 不建议使用的功能列表。
Python 兼容性
虽然这不是一个新功能,但值得注意的是,自 Django 首次公开亮相以来,Django 1.2 首次改变了我们的 Python 兼容性政策。以前的 Django 版本已经过测试并支持从 2.3 开始的 2.x Python 版本;然而,Django 1.2 放弃了对 Python 2.3 的官方支持。因此,现在 Django 所需的最低 Python 版本为 2.4,Django 已经过测试并支持 Python 2.4 、 2.5 和 2.6,并将支持尚未发布的 Python 2.7 。
这个变化应该只会影响少数 Django 用户,因为大多数操作系统供应商现在都默认安装 Python 2.4 或更新的版本。然而,如果你仍然在使用 Python 2.3,那么你需要继续使用 Django 1.1,直到你可以升级为止;根据我们的支持政策,Django 1.1 将在 Django 1.3 发布之前继续获得安全支持。
Django 针对整体 2.x Python 支持的发展路线图以及最终过渡到 Python 3.x 的计划目前正在制定中,并将在 Django 1.3 发布之前宣布。
Django 1.2 新特性
支持多数据库
Django 1.2 增加了在你的 Django 项目中使用 多个数据库 的能力。可以使用 QuerySet
对象上的 using()
方法在特定数据库上发出查询。在调用 save()
时,可以通过提供 using
参数将单个对象保存到特定的数据库。
模型验证
模型实例现在支持 验证自己的数据,而且模型字段和表单字段现在都接受可配置的 验证器列表,指定了可重用的封装的验证行为。但是,请注意,验证仍然必须显式地执行。只是调用模型实例的 save()
方法不会对实例的数据执行任何验证。
改进的 CSRF 保护
Django 现在在防范 跨站请求伪造(CSRF)攻击 方面有了更加完善的保护。这种类型的攻击发生在恶意网站包含一个链接、一个表单按钮或一些 JavaScript,旨在使用已登录用户的凭据在其浏览器中访问恶意网站的用户来执行某些操作。相关的一种攻击类型是“登录 CSRF”,其中攻击站点欺骗用户的浏览器,使其使用别人的凭据登录到某个站点,这也得到了覆盖。
消息框架
Django 现在包括一个强大且可配置的 消息框架,内置支持基于 cookie 和会话的消息传递,适用于匿名和已验证的客户端。消息框架替代了不建议使用的用户消息 API,并允许你在一个请求中临时存储消息,然后在后续请求中检索它们以显示(通常是下一个请求)。
对象级权限
已添加了在每个对象级别指定权限的基础。尽管核心中没有此功能的实现,但自定义身份验证后端可以提供此实现,并将被 django.contrib.auth.models.User 使用。有关更多信息,请参阅 身份验证文档。
匿名用户的权限
如果你提供一个自定义的身份验证后端,并将 supports_anonymous_user
设置为 True
,那么 AnonymousUser 将像 User 一样检查后端的权限。这对于集中处理权限非常有用 - 应用程序始终可以将是否允许某些操作的问题委托给授权/身份验证后端。有关更多详细信息,请参阅 身份验证文档。
放宽用户名要求
内置的 User 模型的 username 字段现在允许更广泛范围的字符,包括 @
、+
、.
和 -
字符。
邮件后端
现在你可以 配置 Django 发送电子邮件的方式。不再使用 SMTP 来发送所有电子邮件,你现在可以选择一个可配置的电子邮件后端来发送消息。如果你的托管提供商使用沙盒或其他非-SMTP 发送邮件的技术,你现在可以构建一个电子邮件后端,使 Django 的标准 邮件发送方法 可以使用这些设施。
这也使得调试邮件发送更加容易。Django 提供了后端实现,允许你将电子邮件发送到 文件、控制台,或 内存。你甚至可以配置所有的电子邮件都被 丢弃。
“智能” if 标签
if 标签已升级为更加强大。首先,我们增加了对比较运算符的支持。你不再需要输入如下内容:
{% ifnotequal a b %}
...
{% endifnotequal %}
现在你可以这样做:
{% if a != b %}
...
{% endif %}
除非你是怀旧型的,否则没有理由再使用 {% ifequal %}
或 {% ifnotequal %}
。
支持的运算符包括 ==
、!=
、<
、>
、<=
、>=
、in
和 not in
,它们都像 Python 运算符一样工作,此外还支持 and
、or
和 not
,这些已经被支持了。
此外,现在可以在 if
表达式中使用过滤器。例如:
<div
{% if user.email|lower == message.recipient|lower %}
class="highlight"
{% endif %}
>{{ message }}</div>
模板缓存
在之前的 Django 版本中,每次渲染模板时都会重新从磁盘加载。在 Django 1.2 中,你可以使用 缓存模板加载器 来加载模板一次,然后为每个后续的渲染缓存结果。如果你的模板被拆分成许多较小的子模板(使用 {% extends %}
或 {% include %}
标签),这可以导致显著的性能提升。
作为一个副作用,现在更容易支持非 Django 模板语言。
基于类的模板加载器
作为引入 模板缓存 所做的更改的一部分,并遵循 Django 中的一般趋势,模板加载器 API 已经被修改为使用封装在 Python 类中的模板加载机制,而不是像 Django 1.1 中只有函数可用。
所有 随 Django 一起提供的模板加载器 都已经转换到新的 API,但它们仍然实现了基于函数的 API,而模板核心机制仍然接受基于函数的加载器(内置或第三方的),因此在现有项目中不需要立即修改你的 TEMPLATE_LOADERS
设置,如果你不更改它,事情将一直正常工作,直到 Django 1.3 版本为止。
如果你已经开发了自己的自定义模板加载器,我们建议考虑将它们移植到基于类的实现,因为在 Django 1.2 中,与基于函数的加载器向后兼容的代码开始被弃用,并将在 Django 1.4 中移除。在模板 API 参考中有关于这些加载器类必须实现的 API 的描述,你还可以查看随 Django 附带的加载器的源代码。
固定装置中的自然键
现在,可以使用 自然键 来引用远程对象的固定数据。这种查找方案是一种替代传统基于主键的对象引用的方式,可以提高可读性,并解决引用那些主键值可能不可预测或未知的对象的问题。
测试的快速失败
django-admin.py
的 test 子命令和用于运行 Django 自己的测试套件的 runtests.py
脚本现在都支持 --failfast
选项。当指定此选项时,测试运行器在遇到失败后会退出,而不是继续运行测试。此外,在测试运行期间改进了对 Ctrl-C
的处理,触发了从测试运行中优雅退出,并报告中断前运行的测试的详细信息。
BigIntegerField
现在,模型可以使用 64 位的 BigIntegerField 类型。
改善的本地化
Django 的 国际化框架 已经扩展了,具备了区域感知的格式化和表单处理功能。这意味着,如果启用了国际化,模板中的日期和数字将使用当前区域设置指定的格式进行显示。Django 还会在解析表单中的数据时使用本地化格式。有关更多详细信息,请参阅 本地格式化。
ModelAdmin
中的 readonly_fields
django.contrib.admin.ModelAdmin.readonly_fields 已经被添加,用于在模型和内联的添加/更改页面上启用不可编辑的字段。字段和计算值可以显示在可编辑字段旁边。
可定制的语法高亮
现在,你可以使用 DJANGO_COLORS 环境变量来修改或禁用 django-admin.py
用于提供 语法高亮 的颜色。
将聚合订阅作为视图
Syndication feeds 现在可以直接用作你的 URLconf 中的视图。这意味着你可以完全控制你的 feeds 的 URL 结构。与任何其他视图一样,feeds 视图会传递一个 request
对象,因此你可以像处理常规视图一样进行操作,如基于用户的访问控制,或将 feed 作为具名 URL。
GeoDjango
在 1.2 版本中,对于 GeoDjango 最重要的新功能之一是对多个空间数据库的支持。因此,现在包括了以下 空间数据库后端:
django.contrib.gis.db.backends.postgis
django.contrib.gis.db.backends.mysql
django.contrib.gis.db.backends.oracle
django.contrib.gis.db.backends.spatialite
GeoDjango 现在支持 PostGIS 1.5 发布中添加的丰富功能。新功能包括对 geography 类型 的支持,并在地理坐标系统上启用了对非点几何图形的 距离查询。
已添加对 3D 几何字段的支持,可以通过在 GeometryField 中设置 dim 关键字为 3 来启用。作为此功能的一部分,还添加了 Extent3D 聚合和 extent3d()
GeoQuerySet
方法。
新添加了 force_rhr()
、reverse_geom()
和 geohash()
GeoQuerySet
方法。
当平台支持时,更新了 GEOS 接口以使用线程安全的 C 库函数。
GDAL 接口现在允许用户在迭代 Layer 时设置 spatial_filter,以过滤返回的要素。
最后,GeoDjango 的文档 现在已经与 Django 的文档一起包括在内,不再单独托管在 geodjango.org
上。
在管理中使用 JavaScript 辅助处理内联相关对象。
如果用户的浏览器启用了 JavaScript,则管理中内联对象的界面现在允许动态添加和删除内联对象。没有启用 JavaScript 的浏览器的用户将不会看到内联对象行为的任何变化。
新的 now
模板标签格式说明符字符:c
和 u
now 的参数新增了两个新的格式字符:c
用于指定将日期时间值格式化为 ISO 8601 格式,u
允许输出日期时间或时间值的微秒部分。
这些新格式字符也在其他地方可用,如 date 和 time 模板过滤器、humanize
模板标签库以及新的 格式本地化 框架。
1.2 版本中的不向后兼容的更改。
尽可能地,上述新功能都是根据我们的 API 稳定性政策以向后兼容的方式引入的。这意味着几乎所有与 Django 1.1 配合使用的现有代码将继续与 Django 1.2 一起工作;然而,这些代码将开始发出警告(详见下文)。
然而,有一些功能确实以一种对某些用户来说立即不向后兼容的方式发生了变化。这些变化将在下面详细说明。
CSRF 保护。
我们对 CSRF 保护的工作方式进行了重大改变,详细信息请参阅 CSRF 文档。以下是你应该注意的主要变化:
CsrfResponseMiddleware
和CsrfMiddleware
已被弃用,并将在 Django 1.4 中完全删除,取而代之的是应该插入到表单中的模板标签。所有的 contrib 应用都使用了一个
csrf_protect
装饰器来保护视图。这需要在模板中使用csrf_token
模板标签。如果你已经使用了自定义模板来定制 contrib 视图,你必须阅读升级说明来修复这些模板。已删除文档
当前 Django 文档中已删除了升级说明。请参考 Django 1.3 或更早版本的文档以查找这些说明。
CsrfViewMiddleware
默认包含在MIDDLEWARE_CLASSES
中。这默认启用了 CSRF 保护,因此接受 POST 请求的视图需要编写以与中间件一起使用。如何做到这一点的说明可以在 CSRF 文档中找到。所有的 CSRF 已经从 contrib 转移到了核心(在旧的位置有向后兼容的导入,这些导入已被弃用,并将在 Django 1.4 中停止支持)。
Field
上的 get_db_prep_*()
方法
在 Django 1.2 之前,自定义的 Field
可以定义多个函数,用于将 Python 值转换为与数据库兼容的值。一个自定义字段可能如下所示:
class CustomModelField(models.Field):
...
def db_type(self):
...
def get_db_prep_save(self, value):
...
def get_db_prep_value(self, value):
...
def get_db_prep_lookup(self, lookup_type, value):
...
在 1.2 版本中,这三种方法的原型发生了变化,还引入了两种额外的方法:
class CustomModelField(models.Field):
...
def db_type(self, connection):
...
def get_prep_value(self, value):
...
def get_prep_lookup(self, lookup_type, value):
...
def get_db_prep_save(self, value, connection):
...
def get_db_prep_value(self, value, connection, prepared=False):
...
def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
...
这些更改是为了支持多个数据库 - db_type
和 get_db_prep_*
不能再对其准备的数据库做任何假设。现在,connection
参数为准备方法提供了特定的连接,用于准备该值。
这两个新方法的存在是为了区分通用的数据准备需求和特定于数据库的需求。prepared
参数用于指示数据库准备方法是否已执行通用值准备。如果将未准备好的值(即 prepared=False
)提供给 get_db_prep_*()
调用,它们应该调用相应的 get_prep_*()
调用来执行通用数据准备。
我们提供了转换函数,可以将符合旧原型的函数透明地转换为与新原型兼容的函数。但是,这些转换函数将在 Django 1.4 中移除,因此你应该尽快升级你的 Field
定义,以使用新的原型。
如果你的 get_db_prep_*()
方法没有使用数据库连接,你应该可以通过将 get_db_prep_value()
重命名为 get_prep_value()
,将 get_db_prep_lookup()
重命名为 get_prep_lookup()
来进行升级。如果你需要数据库特定的转换,那么你需要提供一个实现 get_db_prep_*
的方法,使用 connection
参数来解析数据库特定的值。
有状态的模板标签
将渲染状态存储在其 Node
子类上的模板标签一直容易受到线程安全和其他问题的影响;然而,从Django 1.2开始,当与新的 cached template loader 一起使用时,它们可能也会引发问题。
所有内置的 Django 模板标签都可以安全地与缓存加载器一起使用,但如果你使用的是来自第三方包或你自己的代码的自定义模板标签,你应该确保每个标签的 Node
实现是线程安全的。更多信息,请参阅 模板标签线程安全注意事项。
如果你依赖于 Django 模板标签的实现 不 是线程安全的,你可能还需要更新你的模板。在这种情况下,cycle 标签最有可能受到影响,特别是当与 include 标签一起使用时。考虑以下模板片段:
{% for object in object_list %}
{% include "subtemplate.html" %}
{% endfor %}
带有一个 subtemplate.html
,其内容如下:
{% cycle 'even' 'odd' %}
使用非线程安全的、 Django 1.2 之前的渲染器,输出如下:
even odd even odd ...
使用线程安全的 Django 1.2 渲染器,你将得到:
even even even even ...
这是因为每次渲染 include 标签都是独立的渲染。当 cycle 标签不是线程安全时,cycle 标签的状态会在同一个 include 的多次渲染之间泄漏。现在 cycle 标签是线程安全的,这种泄漏不再发生。
user_passes_test
, login_required
和 permission_required
django.contrib.auth.decorators
提供了装饰器 login_required
、permission_required
和 user_passes_test
。以前可以在函数上使用这些装饰器(其中第一个参数是 ‘request’),也可以在方法上使用(其中第一个参数是 ‘self’,第二个参数是 ‘request’)。不幸的是,发现了支持这种用法的代码存在缺陷:它只在有限的情况下工作,并且在不起作用时会产生非常难以调试的错误。
因此,已经移除了’auto adapt’行为,如果你在方法上使用这些装饰器,你需要手动应用 django.utils.decorators.method_decorator() 来将装饰器转换为适用于方法的装饰器。例如,你需要将代码从这样改为:
class MyClass(object):
@login_required
def my_view(self, request):
pass
改成这个:
from django.utils.decorators import method_decorator
class MyClass(object):
@method_decorator(login_required)
def my_view(self, request):
pass
或者:
from django.utils.decorators import method_decorator
login_required_m = method_decorator(login_required)
class MyClass(object):
@login_required_m
def my_view(self, request):
pass
对于那些一直关注开发主干的人,这个变更也适用于自 1.1 版以来引入的其他装饰器,包括 csrf_protect
、cache_control
和使用 decorator_from_middleware
创建的任何装饰器。
if 标签的变更
由于 if 模板标签中的新功能,它不再接受 ‘and’、’or’ 和 ‘not’ 作为有效的 变量 名称。以前,这些字符串可以用作变量名。现在,关键字状态始终受到强制执行,因此模板代码如 {% if not %}
或 {% if and %}
将引发 TemplateSyntaxError
。此外,in
是一个新关键字,因此在此标签中不是有效的变量名。
LazyObject
LazyObject
是一个未记录但经常使用的实用类,用于懒惰地包装其他未知类型的对象。
在 Django 1.1 及更早版本中,它以一种非标准的方式处理内省,依赖于被包装的对象实现一个名为 get_all_members()
的公共方法。由于这可能会导致名称冲突,因此已更改为使用标准的 Python 内省方法,涉及 __members__
和 __dir__()
。
如果你在自己的代码中使用了 LazyObject
并为被包装的对象实现了 get_all_members()
方法,你需要进行一些更改:
首先,如果你的类对内省没有特殊要求(即,你没有实现 __getattr__()
或其他允许通过正常机制无法发现的属性的方法),你可以简单地删除 get_all_members()
方法。LazyObject
上的默认实现会处理得当。
如果你对内省有更复杂的要求,首先将 get_all_members()
方法重命名为 __dir__()
。这是 Python 2.6 及更高版本的标准内省方法。如果你需要支持早于 2.6 版本的 Python,请将以下代码添加到类中:
__members__ = property(lambda self: self.__dir__())
模型实例上的 __dict__
在历史上,模型实例的 __dict__
属性仅包含与模型上的字段对应的属性。
为了支持多个数据库配置,Django 1.2 添加了一个 _state
属性到对象实例中。这个属性将出现在模型实例的 __dict__
中。如果你的代码依赖于遍历 __dict__
来获取字段列表,现在必须准备好处理或过滤掉 _state
属性。
测试运行器退出状态码
测试运行器(tests/runtests.py
和 python manage.py test
)的退出状态码不再代表失败测试的数量,因为失败 256 个或更多测试会导致错误的退出状态码。现在测试运行器的退出状态码为 0 表示成功(没有失败测试),为 1 表示任何数量的测试失败。如果需要,可以在测试运行器的输出末尾找到测试失败的数量。
Cookie 编码
为了修复 Internet Explorer、Safari 和可能其他浏览器中的 cookie 问题,我们更改了对 cookie 值的编码,以使逗号和分号被视为非安全字符,因此它们被编码为 \054
和 \073
。这可能会导致向后不兼容性,特别是如果你在 cookie 中存储逗号或分号,并且有客户端 JavaScript 代码解析和操作 cookie 值。
ModelForm.is_valid()
和 ModelForm.errors
ModelForms 的大部分验证工作已经移到了模型级别。因此,第一次调用 ModelForm.is_valid()
,访问 ModelForm.errors
或以其他方式触发表单验证时,你的模型将被原地清理。这个转换以前是在模型保存时发生的。如果你需要一个未修改的模型实例,你应该将一个副本传递给 ModelForm
构造函数。
在 MySQL 上的 BooleanField
在之前的 Django 版本中,在 MySQL 下,模型的 BooleanField
会将其值返回为 1
或 0
,而不是 True
或 False
;对于大多数人来说,这不是问题,因为在 Python 中,bool
是 int
的子类。然而,在 Django 1.2 中,MySQL 上的 BooleanField
正确地返回一个真正的 bool
。唯一可能会引发问题的情况是,如果你期望一个 BooleanField
的 repr
打印出 1
或 0
。
对于 FormSets 中 max_num
的解释变更
作为对 FormSets 处理的增强的一部分,max_num
参数在 django.forms.formsets.formset_factory() 和 django.forms.models.modelformset_factory() 函数中的默认值和解释略有变化。这个变更也影响了内联管理对象的 max_num 参数的使用方式。
以前,max_num
的默认值是 0
(零)。FormSets 然后使用 max_num
的布尔值来确定是否要对生成的表单数量设置限制。默认值 0
意味着在 FormSet 中没有默认限制的表单数量。
从 1.2 版本开始,max_num
的默认值已更改为 None
,并且 FormSets 将区分 None
和 0
之间的值。None
表示不限制表单数量;0
表示最多允许 0 个表单。这并不一定意味着不会显示任何表单 - 请参阅 ModelFormSet 文档 获取更多详细信息。
如果你手动指定了 0
作为 max_num
的值,你需要更新你的 FormSet 和/或管理定义。
参见
email_re
一个未记录的用于验证电子邮件地址的正则表达式已从 django.form.fields
移动到了 django.core.validators
。如果你在使用它,你需要更新你的导入。
在 1.2 中被废弃的功能
最后,Django 1.2 弃用了一些早期版本的功能。这些功能仍然受支持,但将在接下来的几个版本周期内逐步淘汰。
使用以下任何功能的代码将在 Django 1.2 中引发 PendingDeprecationWarning
。这个警告默认情况下会被忽略,但可以使用 Python 的 warnings 模块来打开它,或者通过使用 -Wd
或 -Wall
标志来运行 Python 来启用它。
在 Django 1.3 中,这些警告将变为 DeprecationWarning
,它不会被忽略。在 Django 1.4 中,对这些功能的支持将完全移除。
参见
有关更多详细信息,请参阅文档中的 Django 发布过程 和 弃用时间表。
指定数据库
在 Django 1.2 之前,Django 使用了许多设置来控制访问单个数据库。 Django 1.2 引入了对多数据库的支持,因此定义数据库设置的方式发生了变化。
任何现有的 Django 设置文件将继续按预期工作,直到 Django 1.4 。在此之前,旧式数据库设置将自动转换为新式格式。
在旧式(1.2 版之前)的格式中,你的设置文件中有许多 DATABASE_
设置。例如:
DATABASE_NAME = "test_db"
DATABASE_ENGINE = "postgresql_psycopg2"
DATABASE_USER = "myusername"
DATABASE_PASSWORD = "s3krit"
这些设置现在在名为 DATABASES 的字典中。字典中的每个条目对应一个单独的数据库连接,名称为 'default'
描述了默认的数据库连接。设置的名称也已经缩短。之前的示例设置现在会像这样:
DATABASES = {
"default": {
"NAME": "test_db",
"ENGINE": "django.db.backends.postgresql_psycopg2",
"USER": "myusername",
"PASSWORD": "s3krit",
}
}
这影响了以下设置:
旧设置 | 新设置 |
---|---|
DATABASE_ENGINE | ENGINE |
DATABASE_HOST | HOST |
DATABASE_NAME | NAME |
DATABASE_OPTIONS | OPTIONS |
DATABASE_PASSWORD | PASSWORD |
DATABASE_PORT | PORT |
DATABASE_USER | USER |
TEST_DATABASE_CHARSET | TEST_CHARSET |
TEST_DATABASE_COLLATION | TEST_COLLATION |
TEST_DATABASE_NAME | TEST_NAME |
如果你使用所选择的数据库后端手动创建了数据库连接,这些更改也是必需的,可以使用 DatabaseWrapper()
。
除了结构的变更,Django 1.2 还移除了内置数据库后端的特殊处理。现在,所有的数据库后端都必须使用完全限定的模块名来指定(例如,django.db.backends.postgresql_psycopg2
,而不仅仅是 postgresql_psycopg2
)。
postgresql
数据库后端
psycopg1
库自 2005 年 10 月以来没有更新。因此,使用这个库的 postgresql
数据库后端已经被弃用。
如果你目前正在使用 postgresql
后端,你应该迁移到使用 postgresql_psycopg2
后端。要更新你的代码,安装 psycopg2
库,并将 ENGINE 设置更改为使用 django.db.backends.postgresql_psycopg2
。
CSRF 响应重写中间件
CsrfResponseMiddleware
,自动在传出页面的 POST
表单中插入 CSRF 令牌的中间件,已被弃用,推荐使用模板标签方法(见上文),并将在 Django 1.4 中完全移除。同样,包含了 CsrfResponseMiddleware
和 CsrfViewMiddleware
功能的 CsrfMiddleware
也已被弃用。
此外,CSRF 模块已从 contrib 转移到核心,旧的导入已被弃用,如升级说明中所述。
已删除文档
当前 Django 文档中已删除了升级说明。请参考 Django 1.3 或更早版本的文档以查找这些说明。
SMTPConnection
SMTPConnection
类已被弃用,以支持通用的电子邮件后端 API。旧代码中明确实例化 SMTPConnection
实例的方式已被弃用:
from django.core.mail import SMTPConnection
connection = SMTPConnection()
messages = get_notification_email()
connection.send_messages(messages)
…现在应该调用 get_connection() 来实例化一个通用的电子邮件连接:
from django.core.mail import get_connection
connection = get_connection()
messages = get_notification_email()
connection.send_messages(messages)
根据 EMAIL_BACKEND 设置的值,这可能不会返回一个 SMTP 连接。如果你明确需要一个用于发送电子邮件的 SMTP 连接,可以显式请求一个 SMTP 连接:
from django.core.mail import get_connection
connection = get_connection("django.core.mail.backends.smtp.EmailBackend")
messages = get_notification_email()
connection.send_messages(messages)
如果你构造 SMTPConnection
实例的调用需要额外的参数,这些参数可以传递给 get_connection() 调用:
connection = get_connection(
"django.core.mail.backends.smtp.EmailBackend", hostname="localhost", port=1234
)
用户消息 API
通过 user.message_set.create
在用户 Message
模型中存储消息的 API 已被弃用,并将根据标准的 发布流程 在 Django 1.4 中移除。
要升级你的代码,你需要替换所有这样的实例:
user.message_set.create("a message")
… 替换为以下内容:
from django.contrib import messages
messages.add_message(request, messages.INFO, "a message")
此外,如果你使用这个方法,你需要替换以下内容:
for message in user.get_and_delete_messages():
...
… 替换为:
from django.contrib import messages
for message in messages.get_messages(request):
...
有关更多信息,请参阅完整的 消息文档。你应该立即开始更新你的代码以使用新的 API。
日期格式辅助函数
django.utils.translation.get_date_formats()
和 django.utils.translation.get_partial_date_formats()
已被弃用,推荐使用适当的调用 django.utils.formats.get_format()
,当 USE_L10N
设置为 True
时,它是区域感知的,并在设置为 False
时回退到默认设置。
要获得不同的日期格式,而不是编写这样的代码:
from django.utils.translation import get_date_formats
date_format, datetime_format, time_format = get_date_formats()
… 使用:
from django.utils import formats
date_format = formats.get_format("DATE_FORMAT")
datetime_format = formats.get_format("DATETIME_FORMAT")
time_format = formats.get_format("TIME_FORMAT")
或者,在直接格式化日期值时:
from django.utils import formats
value_formatted = formats.date_format(value, "DATETIME_FORMAT")
同样适用于 django.forms.fields
中找到的全局变量:
DEFAULT_DATE_INPUT_FORMATS
DEFAULT_TIME_INPUT_FORMATS
DEFAULT_DATETIME_INPUT_FORMATS
使用 django.utils.formats.get_format()
获取适当的格式。
基于函数的测试运行器
Django 1.2 更改了测试运行工具以使用基于类的方法。旧式的基于函数的测试运行工具仍然可以工作,但应该更新为使用新的 基于类的运行工具。
django.contrib.syndication.feeds
中的 Feed
django.contrib.syndication.feeds.Feed
类已被 django.contrib.syndication.views.Feed 类替代。旧的 feeds.Feed
类已被弃用,并将在 Django 1.4 中移除。
新的类具有几乎相同的 API,但允许将实例用作视图。例如,考虑以下 URLconf 中使用旧框架的示例:
from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory
feeds = {
"latest": LatestEntries,
"categories": LatestEntriesByCategory,
}
urlpatterns = patterns(
"",
# ...
(
r"^feeds/(?P<url>.*)/$",
"django.contrib.syndication.views.feed",
{"feed_dict": feeds},
),
# ...
)
使用新的 Feed 类,这些 feed 可以直接作为视图部署:
from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory
urlpatterns = patterns(
"",
# ...
(r"^feeds/latest/$", LatestEntries()),
(r"^feeds/categories/(?P<category_id>\d+)/$", LatestEntriesByCategory()),
# ...
)
如果你当前使用 feed()
视图,那么 LatestEntries
类通常不需要进行修改,除非它是新的 Feed 类的子类。唯一的例外是如果 Django 自动计算要用于渲染 feed 的描述和标题元素的模板名称(如果你没有指定 title_template
和 description_template
属性)。你应该确保始终指定 title_template
和 description_template
属性,或提供 item_title()
和 item_description()
方法。
然而,LatestEntriesByCategory
使用了 get_object()
方法,并通过 bits
参数指定要显示的特定类别。在新的 Feed 类中,get_object()
方法接受一个 request
和来自 URL 的参数,所以它会像这样:
from django.contrib.syndication.views import Feed
from django.shortcuts import get_object_or_404
from myproject.models import Category
class LatestEntriesByCategory(Feed):
def get_object(self, request, category_id):
return get_object_or_404(Category, id=category_id)
# ...
另外,Feed
类上的 get_feed()
方法现在接受不同的参数,如果你直接使用 Feed
类,这可能会影响你。现在它不仅接受可选的 url
参数,还接受两个参数:它自己的 get_object()
方法返回的对象以及当前的 request
对象。
为了考虑到 Feed
类不会为每个请求初始化,现在默认情况下 __init__()
方法不接受任何参数。以前它会接受来自 URL 的 slug
和 request
对象作为参数。
根据 RSS 最佳实践,RSS 订阅现在将包含一个 atom:link
元素。你可能需要更新你的测试以考虑这一点。
有关更多信息,请参阅完整的 syndication 框架文档。
技术性消息 ID
在版本 1.1 之前,Django 使用技术性的消息 ID 来提供本地化者翻译日期和时间格式的可能性。它们是可翻译的 翻译字符串,可以通过它们都是大写字母来识别(例如 DATETIME_FORMAT, DATE_FORMAT, TIME_FORMAT)。它们已被弃用,推荐使用新的 本地格式化 基础设施,允许本地化者在相应的 django/conf/locale/<locale name>/
目录中的 formats.py
文件中指定这些信息。
GeoDjango
为了支持多个数据库,GeoDjango 数据库内部进行了重大的更改。最大的向后不兼容性更改是模块 django.contrib.gis.db.backend
被重命名为 django.contrib.gis.db.backends,其中现在存在全功能的 空间数据库后端。以下各节提供了关于受这些更改影响最大的 API 的信息。
SpatialBackend
在创建单独的空间后端之前,提供了 django.contrib.gis.db.backend.SpatialBackend
对象,用于内省空间数据库的功能。SpatialBackend
提供的所有属性和例程现在都是数据库后端的 ops
属性的一部分。
旧模块 django.contrib.gis.db.backend
仍然提供了向后兼容的访问 SpatialBackend
对象的方式,它只是默认空间数据库连接的 ops
模块的别名。
依赖于 django.contrib.gis.db.backend
中的未记录模块和对象,而不是 SpatialBackend
提供的抽象的用户需要修改他们的代码。例如,在 1.1 及以下版本中可以正常工作的以下导入:
from django.contrib.gis.db.backend.postgis import PostGISAdaptor
需要进行更改:
from django.db import connection
PostGISAdaptor = connection.ops.Adapter
SpatialRefSys
和 GeometryColumns
模型
在 GeoDjango 的早期版本中,django.contrib.gis.db.models 包含了用于查询 OGC 空间元数据表 spatial_ref_sys
和 geometry_columns
的 SpatialRefSys
和 GeometryColumns
模型。
尽管仍然提供这些别名,但它们仅适用于 默认 数据库连接,并且仅在默认连接使用受支持的空间数据库后端时存在。
备注
由于不同空间数据库的 OGC 空间元数据表的表结构不同,因此不能再将 SpatialRefSys
和 GeometryColumns
模型与 gis
应用程序名称关联。因此,在以下示例中使用 get_models
方法将不会返回任何模型:
>>> from django.db.models import get_app, get_models
>>> get_models(get_app("gis"))
[]
要获取与你的空间数据库匹配的正确的 SpatialRefSys
和 GeometryColumns
,请使用空间后端提供的方法:
>>> from django.db import connections
>>> SpatialRefSys = connections["my_spatialite"].ops.spatial_ref_sys()
>>> GeometryColumns = connections["my_postgis"].ops.geometry_columns()
备注
当使用从 spatial_ref_sys()
和 geometry_columns()
方法返回的模型时,仍然需要在查询非默认连接时使用正确的数据库别名。换句话说,为了确保上面示例中的模型使用正确的数据库:
sr_qs = SpatialRefSys.objects.using("my_spatialite").filter(...)
gc_qs = GeometryColumns.objects.using("my_postgis").filter(...)
语言代码 no
目前使用的挪威博克马尔语的语言代码 no
正在被更常见的语言代码 nb
所取代。
基于函数的模板加载器
Django 1.2 将模板加载机制更改为使用基于类的方法。旧式基于函数的模板加载器仍然可以工作,但应该更新为使用新的基于类的模板加载器。