Django 1.0在某些区域中断了与0.96的兼容性。
本指南将帮助您将0.96项目和应用程序移植到1.0。本文档的第一部分包括运行1.0所需的常见更改。如果在完成第一部分后,代码仍然中断,请检查该部分 Less-common Changes 一系列不太常见的兼容性问题。
参见
这个 1.0 release notes . 该文档更深入地解释了1.0中的新特性;移植指南更关注于帮助您快速更新代码。
本节介绍大多数用户需要在0.96和1.0之间进行的更改。
更改字符串文本 ('foo' )到Unicode文本 (u'foo' )Django现在全部使用Unicode字符串。在大多数地方,原始字符串将继续工作,但更新为使用Unicode文本将避免一些模糊的问题。
见 Unicode数据 详细信息。
对模型文件的常见更改:
maxlength 到 max_length¶重命名你的名字 maxlength 参数 max_length (已更改为与表单字段一致):
__str__ 具有 __unicode__¶替换您的模型 __str__ 函数与A __unicode__ 方法,并确保 use Unicode (u'foo' )用那种方法。
prepopulated_from¶移除 prepopulated_from 模型字段上的参数。它不再有效,已移动到 ModelAdmin 班在 admin.py . 见 the admin 有关对管理员所做更改的详细信息,请参阅下面的。
core¶移除 core 来自模型字段的参数。它不再是必需的,因为等效功能( inline editing )现在由管理界面以不同的方式处理。你不必担心在线编辑,直到你 the admin 下面的部分。现在,删除对 core .
class Admin: 具有 admin.py¶把你所有的内心 class Admin 来自模型的声明。如果你离开他们,他们不会破坏任何东西,但他们也不会做任何事。要向管理员注册应用程序,您将把这些声明移动到 admin.py 文件;参见 the admin 详情请参见下文。
参见
贡献者 djangosnippets__ 已经写了一个脚本 `scan your models.py and generate a corresponding 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) 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) 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 vbl.用一种. admin.site.register() 请一位 admin.py 文件.以下是有关如何重写的更多细节 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):
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):
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`_ _
新管理员提供了大量新功能;您可以在 admin documentation .
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) 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.newforms 具有 django.forms --Django 1.0将 newforms 模块(在0.96中引入)到纯旧 forms . 这个 oldforms 模块也被移除。
如果你已经在使用 newforms 类库,你用了我们推荐的 import 语句语法,只需更改导入语句。
陈旧::
from django import newforms as forms
新::
from django import forms
如果您使用的是旧窗体系统(以前称为 django.forms 和 django.oldforms )你必须重写你的表格。一个好的起点是 forms documentation
替换上载文件的使用--即 request.FILES --作为简单的字典 UploadedFile . 旧词典的语法不再有效。
因此,在这样的观点中:
def my_view(request):
f = request.FILES["file_field_name"]
...
…您需要进行以下更改:
旧(0.96) |
新(1) |
|---|---|
|
|
|
|
|
|
内部实施 django.db.models.FileField 改变了。可见的结果是,您访问这些模型字段的特殊属性(URL、文件名、图像大小等)的方式已经更改。假设您的模型 FileField 被称为 myfile :
旧(0.96) |
新(1) |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
请注意 width 和 height 属性只对 ImageField 领域。有关更多详细信息,请参见 model API 文档。
Paginator 而不是 ObjectPaginator¶这个 ObjectPaginator 在0.96中已被删除并替换为改进版本, 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.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 如果是真的,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):
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):
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):
class MyModel(models.Model):
field_name = models.DecimalField(max_digits=10, decimal_places=3)
...
如果您忘记进行此更改,您将看到有关 FloatField 不服用 max_digits 属性在 __init__ 因为新的 FloatField 不接受与精度相关的参数。
如果您使用的是MySQL或PostgreSQL,则不需要进一步更改。的数据库列类型 DecimalField 和旧的一样 FloatField .
如果您使用的是sqlite,则需要强制数据库以十进制类型查看相应的列,而不是以浮点形式查看。为此,您需要重新加载数据。更改为“使用”后执行此操作 DecimalField 在您的代码中更新了django代码。
警告
首先备份数据库!
对于SQLite,这意味着复制存储数据库的单个文件(该文件的名称是 DATABASE_NAME 在你的 settings.py 文件)。
升级每个应用程序以使用 DecimalField ,您可以执行以下操作,替换 <app> 以下代码中包含每个应用程序的名称:
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml
笔记:
在这个过程的第一步中,记住使用XML格式是很重要的。我们正在利用XML数据转储的一个特性,使通过sqlite将浮点数据移植到小数点成为可能。
在第二步中,您将被要求确认您已准备好丢失相关应用程序的数据。说是;我们将在第三步中恢复此数据。
DecimalField 在进行此更改之前,未在Django附带的任何应用程序中使用,因此您无需担心对任何标准Django型号执行此过程。
如果在上述过程中出现问题,只需将备份的数据库文件复制到原始文件上,然后重新启动。
django.views.i18n.set_language() 现在需要发布请求¶以前,使用了GET请求。旧的行为意味着状态(用于显示站点的区域设置)可以通过GET请求进行更改,这与HTTP规范的建议相反。调用此视图的代码必须确保现在发出了POST请求,而不是GET。这意味着您不能再使用链接访问视图,但必须使用某种形式的表单提交(例如按钮)。
_() 不再内置¶_() (名为单个下划线的可调用对象)不再是MonkeyPatched内置的——也就是说,它不再能在每个模块中神奇地使用。
如果你以前依靠 _() 始终存在,现在应该显式导入 ugettext 或 ugettext_lazy ,并将其命名为 _ 你自己:
from django.utils.translation import ugettext as _
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 报头¶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):
# ... same as above, but then:
c.login(username="myuser", password="mypassword")
django.core.management 已经被大大改造了。
调用代码中的管理服务现在需要使用 call_command . 例如,如果您有一些调用flush和load_数据的测试代码:
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.utils.datastructures.SortedDict 无论你在哪里使用 django.newforms.forms.SortedDictFromList .
因为 django.utils.datastructures.SortedDict.copy 不将deepcopy返回为 SortedDictFromList.copy() 如果您依赖的是Deepcopy,那么您需要更新代码。通过使用 copy.deepcopy 直接。
几乎 all 已重命名和/或重新定位了个数据库后端级别的函数。这些都没有被记录下来,但是如果您使用这些函数中的任何一个,所有这些函数都在 django.db :
旧(0.96) |
新(1) |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5月 28, 2025