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
用一个 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) |
---|---|
|
|
|
|
|
|
|
|
|
|
如果你用的是 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
如果是真的,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) |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12月 18, 2023