将你的应用从 Django 0.96 移植到 1.0

Django 1.0 在某些地方与 0.96 版本是不兼容的。

这个指南会帮助你把 0.96 的项目和应用移植到 1.0 版本。本文档的第一部分包含了需要运行在 1.0上的常见变更。如果通过了第一部分的变更,你的代码依然无法运行,那么请检查 Less-common Changes 不常见的变更部分中列出的兼容问题。

See also

文档 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 管理员模块文件里;查看 管理员 内容了解更多细节。

例如

下面的一个例子 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"}),
    )

See also

  • 更多关于变更的详细信息以及背后的原因都可以在 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.formsdjango.oldforms),那么你要重写你的表单。良好地开始就是从阅读 表单文档 内容

处理上传文件使用新的 API

代替上传文件的用法 -- 那就是,采用 request.FILES 文件请求入口 -- 与含有 UploadedFile 文件上传类的简单字典一样。老的字典句法不再有效了。

因此,看起来就像:

def my_view(request):
    f = request.FILES["file_field_name"]
    ...

...你需要做出如下变更:

老版本 (0.96)

新版本 (1.0)

f['content']

f.read()

f['filename']

f.name

f['content-type']

f.content_type

文件字段使用新API处理

class:django.db.models.FileField 的内部实现已更改。一个明显的结果是您访问特殊属性(URL, filename, image size, 等等)的方式发生了变化。您需要进行以下更改,假设您的模型 FileField 调用 myfile:

老版本 (0.96)

新版本 (1.0)

myfile.get_content_filename()

myfile.content.path

myfile.get_content_url()

myfile.content.url

myfile.get_content_size()

myfile.content.size

myfile.save_content_file()

myfile.content.save()

myfile.get_content_width()

myfile.content.width

myfile.get_content_height()

myfile.content.height

请注意 widthheight 属性仅对: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 中的模块方法。

  • 移除任何对 AnonymousAny 发送者选项的使用;它们不再存在。你仍然可以通过使用 sender=None 接收来自任何发送者的信号。

  • 将你声明的任何自定义信号转换为 django.dispatch.Signal 的实例,而不是匿名对象。

以下是你需要进行的代码更改的快速摘要:

老版本 (0.96)

新版本 (1.0)

def callback(sender)

def callback(sender, **kwargs)

sig = object()

sig = django.dispatch.Signal()

dispatcher.connect(callback, sig)

sig.connect(callback)

dispatcher.send(sig, sender)

sig.send(sender)

dispatcher.connect(callback, sig, sender=Any)

sig.connect(callback, sender=None)

评论

如果你使用的是Django 0.96版的` Django .contrib.comments`应用程序,你需要升级到1.0版引入的新评论应用程序。详细信息请参见升级指导书。

模板标签

spaceless 标签

spaceless 模板标签现在会移除 HTML 标签之间的 所有 空格,而不再保留单个空格。

本地风味

美国本地风味

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 移动