将你的应用从 Django 0.96 移植到 1.0¶
Django 1.0 在某些地方与 0.96 版本是不兼容的。
这个指南会帮助你把 0.96 的项目和应用移植到 1.0 版本。本文档的第一部分包含了需要运行在 1.0上的常见变更。如果通过了第一部分的变更,你的代码依然无法运行,那么请检查 Less-common Changes 不常见的变更部分中列出的兼容问题。
参见
文档 1.0 版本注意事项。这份文档更深入地解释了 1.0 中新的特性;移植指南更多考虑了帮助你快速更新你的代码。
常见变更¶
本部分描述了 0.96 与 1.0 之间的变更,这些变更都是大部分用户会做的事情。
使用 Unicode 字符集¶
逐字地把字符串 ('foo'
) 变成 Unicode 字符串 (u'foo'
)。Django 目前从始至终贯穿地使用 Unicode 字符集字符串。在绝大多数地方,生食字符串会继续有效,但更新成 Unicode 字符串会防止某些含糊的问题出现。
查阅 Unicode 数据 文档了解细节。
模型¶
对于你的模型文件中常见的变更:
maxlength
重命名为 max_length
¶
把你的 maxlength
参数名变成 max_length
(这次参数名的变更是为了与表单区域保持一致):
用 __unicode__
代替 __str__
¶
使用 __unicode__
方法替换你的模型中的 __str__
函数,然后才能确保你使用 使用 Unicode 字符集 (u'foo'
) 中所介绍的方法。
移除 prepopulated_from
¶
删除模型区域中 prepopulated_from
参数。这个参数不再合法,而且已经转移到管理员 admin.py
模块里的 ModelAdmin
类中去了。查阅 管理员 内容了解更多对管理员变更的细节。
移除 core
¶
删除你的模型区域里的 core
参数。这个参数不再需要了,因为相同功能 (参考 行内编辑) 目前已经由后台接口做出不同地处理。你不用再担心行内编辑,除非你在 管理员 部分才考虑行内编辑。目前,删除所有对 core
参数的指向。
用 admin.py
替换 class Admin:
¶
从你的模型里移除所有嵌入 class Admin
管理员类声明。如果你保留这种类的话,不会对任何有影响,但也不会起任何作用。要注册应用程序管理员,你要把这种类的声明移到 admin.py
管理员模块文件里;查看 管理员 内容了解更多细节。
参见
对 djangosnippets 做出的贡献者已经写了一个脚本会 扫描你的 models.py 模型模块后生成一个相应的 admin.py 管理员模块。
例如¶
下面的一个例子 models.py
模型文件含有所有你需要做出的变更:
老版本 (0.96) models.py
:
class Author(models.Model):
first_name = models.CharField(maxlength=30)
last_name = models.CharField(maxlength=30)
slug = models.CharField(maxlength=60, prepopulate_from=("first_name", "last_name"))
class Admin:
list_display = ["first_name", "last_name"]
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
新版本 (1.0) models.py
:
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
slug = models.CharField(max_length=60)
def __unicode__(self):
return "%s %s" % (self.first_name, self.last_name)
新版本 (1.0) admin.py
管理员模块:
from django.contrib import admin
from models import Author
class AuthorAdmin(admin.ModelAdmin):
list_display = ["first_name", "last_name"]
prepopulated_fields = {"slug": ("first_name", "last_name")}
admin.site.register(Author, AuthorAdmin)
管理员¶
在 1.0 版本中最具挑战性的新管理员功能问题之一。Django 管理接口 (django.contrib.admin
) 管理员功能已经完全重构了;许多管理员定义目前都完全从许多模型定义中解构出来,许多框架都重写后使用 Django 的新表单处理库,而且重新设计成具有扩展和自定义能力。
实际中,意味着你要重写所有你的 class Admin
管理员类声明。你已经在上面的 models 中见过了如何替换你的 class Admin
管理员类,就是在 admin.py
管理员模块文件中用一个 admin.site.register()
管理员网页注册调用来替代。下面这些都是一些更详细的如何重写 Admin
管理员声明类的新句法。
使用新的行内句法¶
新的 edit_inline
行内编辑选项都已经移到 admin.py
管理员模块中了。下面有一个例子:
老版本 (0.96):
class Parent(models.Model): ...
class Child(models.Model):
parent = models.ForeignKey(Parent, edit_inline=models.STACKED, num_in_admin=3)
新版本 (1.0):
class ChildInline(admin.StackedInline):
model = Child
extra = 3
class ParentAdmin(admin.ModelAdmin):
model = Parent
inlines = [ChildInline]
admin.site.register(Parent, ParentAdmin)
查阅 InlineModelAdmin 对象 管理员行内文档了解更多细节。
简化 fields
,或使用 fieldsets
¶
老的 fields
句法是非常迷糊的,而且已经被简化过。老的句法依然有效,但你要使用 fieldsets
来代替老旧句法。
老版本 (0.96):
class ModelOne(models.Model):
...
class Admin:
fields = ((None, {"fields": ("foo", "bar")}),)
class ModelTwo(models.Model):
...
class Admin:
fields = (
("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
)
新版本 (1.0):
class ModelOneAdmin(admin.ModelAdmin):
fields = ("foo", "bar")
class ModelTwoAdmin(admin.ModelAdmin):
fieldsets = (
("group1", {"fields": ("foo", "bar"), "classes": "collapse"}),
("group2", {"fields": ("spam", "eggs"), "classes": "collapse wide"}),
)
参见
更多关于变更的详细信息以及背后的原因都可以在 NewformsAdminBranch wiki page 新表单管理分支维基百科页面找到
新的管理员功能伴随着许多新特性;你可以在 管理员文档 中来阅读有关内容。
URLs¶
更新你的根路径 urls.py
模块¶
如果你正在使用后台界面,你需要更新你的根路径``urls.py`` 模块。
老版本 (0.96) urls.py
:
from django.conf.urls.defaults import *
urlpatterns = patterns(
"",
(r"^admin/", include("django.contrib.admin.urls")),
# ... the rest of your URLs here ...
)
新版本 (1.0) urls.py
:
from django.conf.urls.defaults import *
# The next two lines enable the admin and load each admin.py file:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns(
"",
(r"^admin/(.*)", admin.site.root),
# ... the rest of your URLs here ...
)
视图¶
使用 django.forms
来代替 newforms
用法¶
用 django.forms
来替换 django.newforms
用法 -- Django 1.0 版本重命名了 newforms
模块名 (曾用在 0.96 版本的名字) 采用以前用过的 forms
名字。而 oldforms
模块也会被移除。
如果你已经使用 newforms
库的话,而且你采用了我们所建议的 import
导入语句句法,那么所有你要做的就是改变一下你的导入依据即可。
老版本:
from django import newforms as forms
新版本:
from django import forms
如果你正在使用老的表单系统 (正规的名字是 django.forms
和 django.oldforms
),那么你要重写你的表单。良好地开始就是从阅读 表单文档 内容
处理上传文件使用新的 API¶
代替上传文件的用法 -- 那就是,采用 request.FILES
文件请求入口 -- 与含有 UploadedFile
文件上传类的简单字典一样。老的字典句法不再有效了。
因此,看起来就像:
def my_view(request):
f = request.FILES["file_field_name"]
...
...你需要做出如下变更:
老版本 (0.96) |
新版本 (1.0) |
---|---|
|
|
|
|
|
|
文件字段使用新API处理¶
class:django.db.models.FileField 的内部实现已更改。一个明显的结果是您访问特殊属性(URL, filename, image size, 等等)的方式发生了变化。您需要进行以下更改,假设您的模型 FileField
调用 myfile
:
老版本 (0.96) |
新版本 (1.0) |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
请注意 width
和 height
属性仅对:class:~django.db.models.ImageField 字段有意义。更多详细信息可以在 模型 API 文档中找到。
使用 Paginator
而不是 ObjectPaginator
¶
0.96 版本中的 ObjectPaginator
已被删除,并替换为一个改进版本: class:django.core.paginator.Paginator。
模板¶
学会爱上自动转义¶
默认情况下,模板系统现在会自动对每个变量的输出进行HTML转义。要了解更多信息,请参阅 自动 HTML 转义。
要禁用单个变量的自动转义,请使用 safe
过滤器:
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
要禁用整个模板的自动转义,请将模板(或模板的特定部分)包装在 autoescape
标签:
{% autoescape off %}
... unescaped template content here ...
{% endautoescape %}
不常见的变化¶
以下更改是较小的、更本地化的更改。它们应该只影响更高级的用户,但是通读列表并检查代码中的这些东西可能是值得的。
信号¶
将``**kwargs``添加到任何注册的信号处理程序中。
通过
Signal
对象上的方法连接、断开连接和发送信号,而不是通过django.dispatch.dispatcher
中的模块方法。移除任何对
Anonymous
和Any
发送者选项的使用;它们不再存在。你仍然可以通过使用sender=None
接收来自任何发送者的信号。将你声明的任何自定义信号转换为
django.dispatch.Signal
的实例,而不是匿名对象。
以下是你需要进行的代码更改的快速摘要:
老版本 (0.96) |
新版本 (1.0) |
---|---|
|
|
|
|
|
|
|
|
|
|
评论¶
如果你使用的是Django 0.96版的` Django .contrib.comments`应用程序,你需要升级到1.0版引入的新评论应用程序。详细信息请参见升级指导书。
本地风味¶
美国本地风味¶
django.contrib.localflavor.usa
已重命名为 django.contrib.localflavor.us
。此更改是为了与其他本地化风格的命名方案匹配。要迁移你的代码,你只需要更改导入语句。
会话¶
获取新的会话密钥¶
SessionBase.get_new_session_key()
已重命名为 _get_new_session_key()
。get_new_session_object()
不再存在。
辅助工具¶
加载一行不再调用"save()"¶
以前加载一行数据会自动运行模型的`save()`方法。现在情况不再是这样了,所以任何由``save()``自动填充的字段(例如:时间戳)现在都需要在任何fixture中显示值。
配置¶
更好的异常处理¶
旧的 EnvironmentError
现已拆分为 ImportError
(当 Django 无法找到设置模块时)和 RuntimeError
(当你尝试在已经使用过设置之后重新配置它们时)。
LOGIN_URL
已移动¶
LOGIN_URL
常量已从 django.contrib.auth
移动到 settings
模块。不再使用 from django.contrib.auth import LOGIN_URL
,请改用 settings.LOGIN_URL
。
APPEND_SLASH
的行为已更新。¶
在 0.96 版本中,如果一个 URL 不以斜杠结尾,或者其路径的最后一个组件中没有句点,并且 APPEND_SLASH
为 True,Django 会重定向到相同的 URL,但在末尾添加斜杠。现在,Django 会检查去掉尾部斜杠的模式是否与你的 URL 模式中的某些内容匹配。如果匹配成功,不会进行重定向,因为假定你是有意捕获该模式的。
对大多数人来说,这不需要进行任何更改。然而,有些人的 URL 模式看起来像这样:
r"/some_prefix/(.*)$"
以前,这些模式会被重定向以添加尾部斜杠。如果你希望这些 URL 始终带有斜杠,请将模式改写为:
r"/some_prefix/(.*/)$"
较小的模型更改¶
与``get()``不同的异常¶
现在,管理器返回 MultipleObjectsReturned
异常,而不再返回 AssertionError
异常:
老版本 (0.96):
try:
Model.objects.get(...)
except AssertionError:
handle_the_error()
新版本 (1.0):
try:
Model.objects.get(...)
except Model.MultipleObjectsReturned:
handle_the_error()
LazyDate
已删除。¶
LazyDate
帮助类不再存在。
默认字段值和查询参数都可以是可调用对象,因此可以将 LazyDate
的实例替换为对 datetime.datetime.now
的引用:
老版本 (0.96):
class Article(models.Model):
title = models.CharField(maxlength=100)
published = models.DateField(default=LazyDate())
新版本 (1.0):
import datetime
class Article(models.Model):
title = models.CharField(max_length=100)
published = models.DateField(default=datetime.datetime.now)
DecimalField
是新的,而 FloatField
现在是真正的浮点数字段。¶
老版本 (0.96):
class MyModel(models.Model):
field_name = models.FloatField(max_digits=10, decimal_places=3)
...
新版本 (1.0):
class MyModel(models.Model):
field_name = models.DecimalField(max_digits=10, decimal_places=3)
...
如果你忘记进行这个更改,你会看到关于 FloatField
在 __init__
中不接受 max_digits
属性的错误,因为新的 FloatField
不接受与精度相关的参数。
如果你使用的是 MySQL 或 PostgreSQL,不需要进一步的更改。对于 DecimalField
,数据库列类型与旧的 FloatField
相同。
如果你使用的是 SQLite,你需要强制数据库将相应的列视为十进制类型,而不是浮点数。要做到这一点,你需要在对代码进行更改并更新 Django 代码后重新加载数据。
警告
首先备份你的数据库!!!!
对于SQLite,这意味着要复制存储数据库的单个文件(该文件的名称是``settings.py``文件中的``DATABASE_NAME``)。
要升级每个应用程序以使用 DecimalField
,你可以按照以下代码进行操作,将代码中的 <app>
替换为每个应用程序的名称:
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml
注意:
在这个过程的第一步中,重要的是记住要使用 XML 格式。我们利用了 XML 数据转储的一个特性,使得将浮点数转换为 SQLite 中的十进制数成为可能。
在第二步中,你将被要求确认你是否准备好丢失相关应用程序的数据。选择是;我们将在第三步中恢复这些数据。
在这个更改之前,Django 附带的应用程序中没有使用
DecimalField
,所以你不需要担心为任何标准的 Django 模型执行此过程。
如果上述过程出现问题,只需将备份的数据库文件复制到原始文件上,然后重新开始。
国际化¶
django.views.i18n.set_language()
现在要求使用 POST 请求。¶
以前使用的是 GET 请求。旧的行为意味着可以通过 GET 请求更改状态(用于显示站点的区域设置),这违反了 HTTP 规范的建议。调用此视图的代码必须确保现在进行的是 POST 请求,而不是 GET 请求。这意味着你不能再使用链接来访问视图,而是必须使用某种表单提交方式(例如按钮)。
_()
不再位于内置函数中¶
_()
(其名称为单个下划线的可调用对象)不再被自动添加到内置函数中,也就是说,它不再在每个模块中自动可用。
如果你之前依赖于 _()
总是存在,现在应该显式导入 ugettext
或 ugettext_lazy
(如果适用),并自己将其别名为 _
:
from django.utils.translation import ugettext as _
HTTP 请求/响应对象¶
对于 HttpRequest
的字典访问:¶
HttpRequest
对象不再直接支持字典风格的访问;以前,GET
和 POST
数据都可以直接在 HttpRequest
对象上使用(例如,你可以通过 if 'some_form_key' in request
或读取 request['some_form_key']
来检查表单数据。不再支持这种方式;如果你需要访问组合的 GET
和 POST
数据,请使用 request.REQUEST
。
然而,强烈建议你始终明确查找你期望接收的请求类型的字典(request.GET
或 request.POST
);依赖于组合的 request.REQUEST
字典可能会掩盖传入数据的来源。
访问``HTTPResponse`` headers¶
django.http.HttpResponse.headers
已重命名为 _headers
,并且 HttpResponse
现在直接支持包含检查。所以使用 if header in response:
而不是 if header in response.headers:
。
通用关系¶
通用关系已从核心中移出。¶
通用关联类 -- GenericForeignKey
和 GenericRelation
-- 已移动到 django.contrib.contenttypes
模块。
测试中¶
django.test.Client.login()
发生了变化¶
老版本 (0.96):
from django.test import Client
c = Client()
c.login("/path/to/login", "myuser", "mypassword")
新版本 (1.0):
# ... same as above, but then:
c.login(username="myuser", password="mypassword")
管理命令¶
从你的代码中运行管理命令¶
django.core.management
已经进行了大规模的重构。
你的代码中对管理服务的调用现在需要使用 call_command
。例如,如果你有一些调用 flush 和 load_data 的测试代码:
from django.core import management
management.flush(verbosity=0, interactive=False)
management.load_data(["test_data"], verbosity=0)
...你需要更改这段代码为:
from django.core import management
management.call_command("flush", verbosity=0, interactive=False)
management.call_command("loaddata", "test_data", verbosity=0)
现在子命令必须在选项之前。¶
django-admin.py
和 manage.py
现在要求子命令必须在选项之前。因此:
$ django-admin.py --settings=foo.bar runserver
...不再起作用,应该改为:
$ django-admin.py runserver --settings=foo.bar
数据结构¶
SortedDictFromList
已被移除¶
django.newforms.forms.SortedDictFromList
已被移除。django.utils.datastructures.SortedDict
现在可以通过元组序列进行实例化。
要更新你的代码:
在原先使用
django.newforms.forms.SortedDictFromList
的地方,现在应该使用django.utils.datastructures.SortedDict
。因为
django.utils.datastructures.SortedDict.copy
不像SortedDictFromList.copy()
那样返回深拷贝,如果你依赖于深拷贝,你需要更新你的代码。通过直接使用copy.deepcopy
来实现这一点。
数据库后端函数¶
数据库后端函数已经改名。¶
几乎所有数据库后端级别的函数都已被重命名和/或移动。虽然这些函数没有被文档化,但如果你使用了其中的任何一个函数,你需要修改你的代码,所有这些函数都在 django.db
中:
老版本 (0.96) |
新版本 (1.0) |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|