Django v1.0 documentation

アプリケーションを Django 0.96 から 1.0 に移行する

revision-up-to:8961 (1.0)

Django 1.0 は、いくつかの点で 0.96 との互換性を失っています。

このガイドは、 0.96 のプロジェクトやアプリケーションを 1.0 に移行する手助け として書かれています。ドキュメントの最初の部分には、 1.0 で動作させるために 必要な変更のうち、よくあるものを説明しています。この部分の説明に従って移行 しても、まだ動作しないようなら、 ややマイナーな変更 を参照して、細かな変更に基づく互換性の問題について 調べてください。

See also

このポーティングガイドでは、コードを手早く移行することに焦点を絞ってい ますが、 1.0 リリースノート では、 1.0 で登場した 新しい機能をより詳しく解説しています。

一般的な変更

この節では、 0.96 から 1.0 への移行の際に大半のユーザが行わねばならない変更 を解説しています。

Unicode を使う

文字列リテラル ('foo') を Unicode リテラル (u'foo') に変更してくだ さい。 Django は全体で一貫して Unicode を使うようになりました。ほとんどの場 所で、通常の文字列はそのまま使えますが、 Unicode リテラルを明示的に使ってお けば、ややこしい問題が発生するのを防げます。

詳しくは Django での Unicode の扱い を参照してください。

モデル

モデルファイルにおける大きな変更は、以下の通りです:

maxlengthmax_length に変更する

maxlength 引数を max_length に変更してください (フォームフィールド との一貫性のための変更です)。

__str____unicode__ に置き換える

モデルの __str____unicode__ メソッドに置き換え、メソッドから Unicode を返す (u'foo') ようにしてください。

prepopulated_from をなくす

モデルフィールドから prepopulated_from 引数をなくしてください。この引数 はもう有効でなく、 AdminModel クラスの admin.py に移されました。 admin に関する詳しい変更内容は、後述の admin の変更 を参照し てください。

class Admin:admin.py と置き換える

モデルから class Admin 宣言を除去してください。モデル内にそのまま残って いても影響はありませんが、何の効果もありません。アプリケーションを admin に 登録するには、 admin.py ファイルに宣言を移す必要があります。詳しくは admin の変更 を参照してください。

admin の変更例

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 u'%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)

admin の変更

1.0 で追加された大きな変更の一つに、新しい admin API があります。 Django の 管理インタフェース (django.contrib.admin) は完全にリファクタされました。 admin の定義は完全にモデル定義から脱カップリングされ、admin のフレームワー クは Django の新たなフォーム処理ライブラリを使うよう書き直されました。また、 思い通りに拡張したりカスタマイズしたりできるようになりました。

この変更により、 class Admin 宣言を全て書き直す必要があります。 class Admin から admin.py ファイルの admin.site.register() 呼び 出しへの変更方法は、 モデルの変更 ですでに触れました。 以下では、 Admin 宣言を新たな書式に書き換える上で必要な細かい点について 説明します。

See also

djangosnippets のコントリビュータの一人が、 models.py をスキャンして admin.py を生成するスクリプト を書いていま す。

インラインの宣言方法

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(models.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

URLs

ルート urls.py を修正する

admin サイトをルートの 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 ...
)

ビュー

newforms の代わりに django.forms を使う

django.newformsdjango.forms に置き換えてください。 Django 1.0 は (0.96 で登場した) newforms モジュールを単に forms と呼びます。 oldforms はなくなりました。

すでに新しいフォームを使っているのなら、 import 文を変更するだけです。 from django import newforms as forms から from django import forms に書き換えてください。

古いフォームシステムを使っているのなら、フォームを書き直す必要があります。 まずは forms のドキュメント を読むところから始 めてください。

アップロードファイルの処理に新しい 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

テンプレート

オートエスケープを使う

テンプレートシステムは、デフォルトで変数の出力に自動 HTML エスケープを施す ようになりました。詳しくは HTML の自動エスケープ を参照してくださ い。

個々の変数に対する自動エスケープを無効化するには、 safe フィルタ を使ってください:

エスケープされるよ: {{ data }}
エスケープされないよ: {{ data|safe }}

テンプレート全体で自動エスケープを無効にするには、テンプレート (や、テンプ レートの特定の部分) を autoescape タグで囲います:

{% autoescape off %}
   ... unescaped template content here ...
{% endautoescape %}

よりマイナーな変更

以下の変更は、些細で特殊なものです。これらの変更によって影響を受けるのは、 ごく一部の高度な使い方をしているユーザだけでしょう。とはいえ、この節を一読 して、自分のコードに当てはまる部分がないかチェックする価値はあるでしょう。

シグナル

  • シグナルハンドラには全て **kwargs を追加してください。
  • シグナルハンドラの接続と解除、シグナルの送信は、 django.dispatch.dispatcher のモジュールメソッドではなく、 Signal オブジェクトのメソッドを使ってください。
  • sender オプションの指定から、 Anonymous および Any を外してく ださい。これらのシンボルはもうありません。全てのセンダからシグナルを受け 取りたければ、 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 で登場した新たなコメントアプリケーションに移行してください。詳し くは Django の以前のコメントシステムからの移行 で解説しています。

テンプレートタグ

spaceless タグ

HTML タグ間のスペースを除去する spaceless タグは、以前はスペースを 一つだけ残していましたが、 全て を除去するようになりました。

ローカルフレーバ

US ローカルフレーバ

django.contrib.localflavor.usadjango.contrib.localflavor.us に変更されました。他のローカルフレーバと命名方法を統一するためです。

セッション

新たなセッションキーの取得

SeesionBase.get_new_session_key()_get_new_session_key() にリネー ムされました。 get_new_session_object() はもうありません。

フィクスチャ

行レコードのロード時に save() が呼ばれなくなる

以前は、レコード行を読むたびに、自動的にモデルの save() メソッドが呼び 出されていました。この仕様は変更され、呼び出されなくなりました。そのため、 (タイムスタンプなどの) save() 時に自動的に値が入るフィールドがある場合、 フィクスチャ側に値を持たせる必要があります。

設定

例外の改善

以前の EnvironmentErrorImportErrorRuntimeError に分割されました。 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_SLASHTrue だと、末尾にスラッシュを付加した URL にリダイレクトしていました。 1.0 では、明示的にスラッシュのないパターンを URL パターンでキャッチできるように、末尾にスラッシュのない URL に対して、 まず URL パターン中に一致するエントリがないか調べ、あればリダイレクトしなく なりました。

ほとんどのユーザはこの仕様変更の影響を受けませんが、以下のような URL パター ンを書いている一部のユーザは影響を受けます:

r'/some_prefix/(.*)$'

以前は、こうしたパターンを書いている場合、まず末尾にスラッシュのある URL に リダイレクトしていました。 URL の末尾に必ずスラッシュが入っているようなパターンを書きたいなら、以下のようにパターンを書き換えてください:

r'/some_prefix/(.*/)$'

モデルに関する細かい変更

get() の例外

モデルマネジャは AssertionError ではなく MultipleObjectsReturned 例外を返すようになりました。

旧 (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 はなくなりました。

フィールド値やクエリ引数に呼び出し可能オブジェクトを指定できるようになった ので、 LazyDatedatetime.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(maxlength=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 には精度桁数に関する引 数がないので、 FloatField__init__ には max_digits という属 性がない、という旨のエラーを受け取ります。

MySQL や PostgreSQL を使っている場合、これ以上の変更は必要ありません。 DecimalField のデータベースカラム型は、旧来の FloatField と同じだか らです。

SQLite を使っている場合、データベースに対して、データを decimal 型でなく float 型として扱うよう教え直す必要があります。そのために、データをリロード してください。データのリロードは、 DecimalField への変更を終えて、 Django をアップデートした後に行ってください。

Warning

データベースを先にバックアップしてください!

SQLite を使っている場合、データベースのバックアップするには、単にデータベー スの保存されているファイル (settings.pyDATABASE_NAME に指定し ているファイル名) をコピーします。

DecimalField を使う全てのアプリケーションについて以下の作業を行ってくだ さい。 <app> はアプリケーションのなめに読み変えます:

$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml

注意:

  1. 作業の最初のステップでは、必ずダンプ形式に XML を指定してください。と いうのも、このステップでは、 XML データダンプによって、 float データが SQLite で扱える decimal に変換されるという仕様を使っているからです。
  2. 二つめのステップでは、アプリケーションのデータが失われてもよいか尋ねら れます。 yes と答えてください。もちろん、三つ目のステップでデータを復 元しますからね。
  3. DecimalField に関する仕様変更前からある Django 付属のアプリケーショ ンは、全て影響を受けません。したがって、標準の Django モデルに対してこ の操作を行う必要はありません。

上のプロセスでうまく行かないようなら、バックアップしておいたデータベースファ イルをデータベースファイルに上書きして、Django を再起動してください。

国際化

django.views.i18n.set_language() には POST リクエストが必要

以前は、 GET リクエストが使われていました。この動作は、サーバの状態 (サイト を表示する際のロケール) を GET リクエストで変更できることになり、 HTTP 仕様 の勧告に違反しています。 1.0 からは、このビューを呼び出すときには、GET では なく POST リクエストを使わねばならなくなりました。そのため、このビューは リンクを使ってアクセスできず、ボタンなどを使ってフォームを提出せねばならな くなりました。

_() は組み込みでなくなりました

以前は、モンキーパッチによって _() を組み込み名前空間にいれていました。 そのため、 _() が常に存在することを前提としてコードを書いている場合、 ugettextugettext_lazy のどちらか適切な方を明示的に import して、 _ という別名をつけねばなりません:

from django.utils.translation import ugettext as _

HTTP リクエスト/レスポンスオブジェクト

HTTPResponse ヘッダへのアクセス

django.http.HttpResponse.headers_headers にリネームされ、 HttpResponse` はヘッダの包含チェックを直接サポートするようになりま した。従って、 if header in response.headers: ではなく if header in response: と書いてください。

一般化リレーション

一般化リレーションはコアパッケージから移動しました

一般化リレーションのクラス、 GenericForeignKey および GenericRelation は、 django.contrib.contenttypes モジュールに移 動しました。

テスト

django.test.Client.login() の変更

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 を使う必 要があります。例えば、 flushload_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.pymanage.py に引数を指定するとき、サブコマンドはオ プションよりも前に置かねばならなくなりました。従って:

$ django-admin.py --settings=foo.bar runserver

はもう使えず、以下のように変更せねばなりません:

$ django-admin.py runserver --settings=foo.bar

配信フィード

Feed.__init__ の変更

配信フィードフレームワークの Feed クラスの __init__() パラメタは、 第二引数にフィードの URL ではなく HttpRequest オブジェクトを取るように なりました。この変更によって、配信フィードフレームワークは sites フレームワー クがなくても動作するようになりました。 Feed をサブクラス化して、 __init__() をオーバライドするコードや、 Feed.__init__() を直接呼び 出しているコードが影響を受けます。

データ構造

SortedDictFromList の撤廃

django.newforms.forms.SortedDictFromList` はなくなりました。その代わり、 タプルのシーケンスを使って django.utils.datastructures.SortedDict` をインスタンス化できるようになりました。

コードを変更するには、以下のように書き換えてください:

  1. django.newforms.forms.SortedDictFromList を使っている部分を django.utils.datastructures.SortedDict に書き換えてくださ い。
  2. django.utils.datastructures.SortedDict.copy()SortedDictFromList メソッドのように、深いコピーを返すので、 コードを deepcopy に対応して書き換える必要があります。深いコピーを 作成するには、 copy.deepcopy を直接呼び出します。

データベースバックエンドの関数

データベースバックエンドの関数名の変更

データベースバックエンドレベルの関数の名前は、ほとんど すべて 変更され、 場所が変わっているものもあります。この変更はドキュメントで一切説明されてい ませんが、自分のコードでこれらの関数を使っていたのなら、名前を変更する必要 があるでしょう。関数は全て django.db パッケージ下にあります:

旧 (0.96) 新 (1.0)
backend.get_autoinc_sql connection.ops.autoinc_sql
backend.get_date_extract_sql connection.ops.date_extract_sql
backend.get_date_trunc_sql connection.ops.date_trunc_sql
backend.get_datetime_cast_sql connection.ops.datetime_cast_sql
backend.get_deferrable_sql connection.ops.deferrable_sql
backend.get_drop_foreignkey_sql connection.ops.drop_foreignkey_sql
backend.get_fulltext_search_sql connection.ops.fulltext_search_sql
backend.get_last_insert_id connection.ops.last_insert_id
backend.get_limit_offset_sql connection.ops.limit_offset_sql
backend.get_max_name_length connection.ops.max_name_length
backend.get_pk_default_value connection.ops.pk_default_value
backend.get_random_function_sql connection.ops.random_function_sql
backend.get_sql_flush connection.ops.sql_flush
backend.get_sql_sequence_reset connection.ops.sequence_reset_sql
backend.get_start_transaction_sql connection.ops.start_transaction_sql
backend.get_tablespace_sql connection.ops.tablespace_sql
backend.quote_name connection.ops.quote_name
backend.get_query_set_class connection.ops.query_set_class
backend.get_field_cast_sql connection.ops.field_cast_sql
backend.get_drop_sequence connection.ops.drop_sequence_sql
backend.OPERATOR_MAPPING connection.operators
backend.allows_group_by_ordinal connection.features.allows_group_by_ordinal
backend.allows_unique_and_pk connection.features.allows_unique_and_pk
backend.autoindexes_primary_keys connection.features.autoindexes_primary_keys
backend.needs_datetime_string_cast connection.features.needs_datetime_string_cast
backend.needs_upper_for_iops connection.features.needs_upper_for_iops
backend.supports_constraints connection.features.supports_constraints
backend.supports_tablespaces connection.features.supports_tablespaces
backend.uses_case_insensitive_names connection.features.uses_case_insensitive_names
backend.uses_custom_queryset connection.features.uses_custom_queryset