revision-up-to: | 9084 (1.0) |
---|
Django 1.0 は、いくつかの点で 0.96 との互換性を失っています。
このガイドは、 0.96 のプロジェクトやアプリケーションを 1.0 に移行する手助け として書かれています。ドキュメントの最初の部分には、 1.0 で動作させるために 必要な変更のうち、よくあるものを説明しています。この部分の説明に従って移行 しても、まだ動作しないようなら、 ややマイナーな変更 を参照して、細かな変更に基づく互換性の問題について 調べてください。
See also
このポーティングガイドでは、コードを手早く移行することに焦点を絞ってい ますが、 1.0 リリースノート では、 1.0 で登場した 新しい機能をより詳しく解説しています。
この節では、 0.96 から 1.0 への移行の際に大半のユーザが行わねばならない変更 を解説しています。
文字列リテラル ('foo'
) を Unicode リテラル (u'foo'
) に変更してくだ
さい。 Django は全体で一貫して Unicode を使うようになりました。ほとんどの場
所で、通常の文字列はそのまま使えますが、 Unicode リテラルを明示的に使ってお
けば、ややこしい問題が発生するのを防げます。
詳しくは Django での Unicode の扱い を参照してください。
モデルファイルにおける大きな変更は、以下の通りです:
maxlength
を max_length
に変更する¶maxlength
引数を max_length
に変更してください (フォームフィールド
との一貫性のための変更です)。
__str__
を __unicode__
に置き換える¶モデルの __str__
を __unicode__
メソッドに置き換え、メソッドから
Unicode を返す (u'foo'
) ようにしてください。
prepopulated_from
をなくす¶モデルフィールドから prepopulated_from
引数をなくしてください。この引数
はもう有効でなく、 ModelAdmin
クラスの admin.py
に移されました。
admin に関する詳しい変更内容は、後述の admin の変更 を参照し
てください。
core
の削除¶core
引数がモデルフィールドより削除されました。これは、
同様の関数( インラインエディット )が
アドミンインターフェースによって、別に動作するようになったため
もう必要なくなったからです。インラインエディットについて心配する必要は
ありません。 the admin セクションで core
へ参照していた全ての
除去されたものたちについて解説しています。
class Admin:
を admin.py
と置き換える¶モデルから class Admin
宣言を除去してください。モデル内にそのまま残って
いても影響はありませんが、何の効果もありません。アプリケーションを admin に
登録するには、 admin.py
ファイルに宣言を移す必要があります。詳しくは
admin の変更 を参照してください。
See also
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 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)
1.0 で追加された大きな変更の一つに、新しい admin API があります。 Django の
管理インタフェース (django.contrib.admin
) は完全にリファクタされました。
admin の定義は完全にモデル定義から脱カップリングされ、admin のフレームワー
クは Django の新たなフォーム処理ライブラリを使うよう書き直されました。また、
思い通りに拡張したりカスタマイズしたりできるようになりました。
この変更により、 class Admin
宣言を全て書き直す必要があります。
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
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.newforms
を django.forms
に置き換えてください。 Django 1.0
は (0.96 で登場した) newforms
モジュールを単に forms
と呼びます。
oldforms
はなくなりました。
すでに newforms
ライブラリを使っていて、 import 文を推奨の書き方で書い
ているのなら、 import 文を変更するだけです。
from django import newforms as forms
から from django import forms
に書き換えてください:
旧:
from django import newforms as forms
新:
from django import forms
古いフォームシステム (以前は django.forms
と呼ばれていた
django.oldforms
)を使っているのなら、フォームを書き直す必要があります。
まずは forms のドキュメント を読むところから始
めてください。
アップロードファイルを扱うコードを書き換えてください。すなわち、これまでの
コードでは 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 |
django.db.models.FileField
の内部の実装が変わりました。
これが返すビジブルな結果はこれらのモデルフィールドが変えた、
特別な要素に対してアクセスする方法となります。
( URL, ファイルネーム, イメージサイズ, 等)
次の変更をする必要があります、
モデルの FileField
が myfile
と
呼ばれているとして:
Old (0.96) | New (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 |
width
と height
アトリビュートは、ただ
ImageField
を通したフィールドです。
もっと詳しいことは、 model API
ドキュメントに載っています。
ObjectPaginator
の代わりとして Paginator
を使う¶0.96 の ObjectPaginator
は取り除かれ、代わりに進歩したバージョンの
ものに取って代わられました、それが django.core.paginator.Paginator
です。
テンプレートシステムは、デフォルトで変数の出力に自動 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 の以前のコメントシステムからの移行 で解説しています。
django.contrib.localflavor.usa
は django.contrib.localflavor.us
に変更されました。他のローカルフレーバと命名方法を統一するためです。
コードを移植する際には import を書き換えてください。
SessionBase.get_new_session_key()
は _get_new_session_key()
にリネー
ムされました。 get_new_session_object()
はもうありません。
save()
が呼ばれなくなる¶以前は、レコード行を読むたびに、自動的にモデルの save()
メソッドが呼び
出されていました。この仕様は変更され、呼び出されなくなりました。そのため、
(タイムスタンプなどの) save()
時に自動的に値が入るフィールドがある場合、
フィクスチャ側に値を持たせる必要があります。
以前の EnvironmentError
は ImportError
と RuntimeError
に分かれました。 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
だと、
末尾にスラッシュを付加した 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
はなくなりました。
フィールド値やクエリ引数に呼び出し可能オブジェクトを指定できるようになった
ので、 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(maxl_ength=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.py
の DATABASE_NAME
に指定し
ているファイル名) をコピーします。
DecimalField
を使う全てのアプリケーションについて、 <app>
をアプリ
ケーションの名前に読み替えて以下の作業を行うとよいでしょう:
$ ./manage.py dumpdata --format=xml <app> > data-dump.xml
$ ./manage.py reset <app>
$ ./manage.py loaddata data-dump.xml
注意:
DecimalField
に関する仕様変更前からある Django 付属のアプリケーショ
ンは、全て影響を受けません。したがって、標準の Django モデルに対してこ
の操作を行う必要はありません。上のプロセスでうまく行かないようなら、バックアップしておいたデータベースファ イルをデータベースファイルに上書きして、Django を再起動してください。
django.views.i18n.set_language()
には POST リクエストが必要¶以前は、 GET リクエストが使われていました。この動作は、サーバの状態 (サイト を表示する際のロケール) を GET リクエストで変更できることになり、 HTTP 仕様 の勧告に違反しています。 1.0 からは、このビューを呼び出すときには、GET では なく POST リクエストを使わねばならなくなりました。そのため、このビューは リンクを使ってアクセスできず、ボタンなどを使ってフォームを提出せねばならな くなりました。
_()
は組み込みでなくなりました¶以前は、モンキーパッチによって _()
(名前がアンダースコア一文字の呼び出
し可能オブジェクト)を組み込み名前空間に入れていましたが、これをやめたため、
_()
を魔法のように常に使えなくなりました。
_()
の存在を前提としてコードを書いている場合、 ugettext
や
ugettext_lazy
のどちらか適切な方を明示的に import して、 _
という別
名をつけねばなりません:
from django.utils.translation import ugettext as _
HttpRequest
への辞書的なアクセス¶HttpRequest
オブジェクトはもはや直接的に辞書式にアクセスすることを
サポートしなくなりました、 GET
と POST
両方のデータは
直接的に HttpRequest
オブジェクトで扱えました(すなわち、
HttpRequest
object (すなわち、 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
にリネームされ、
django.http.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
を使う必
要があります。例えば、 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
Feed.__init__
の変更¶配信フィードフレームワークの Feed
クラスの __init__()
パラメタは、
第二引数にフィードの URL ではなく HttpRequest
オブジェクトを取るように
なりました。この変更によって、配信フィードフレームワークは sites フレームワー
クがなくても動作するようになりました。 Feed
をサブクラス化して、
__init__()
をオーバライドするコードや、 Feed.__init__()
を直接呼び
出しているコードが影響を受けます。
SortedDictFromList
の撤廃¶django.newforms.forms.SortedDictFromList
はなくなりました。その代わり、
タプルのシーケンスを使って django.utils.datastructures.SortedDict
をインスタンス化できるようになりました。
コードを変更するには、以下のように書き換えてください:
django.newforms.forms.SortedDictFromList
を使っている部分を
django.utils.datastructures.SortedDict
に書き換えてくださ
い。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 |
Oct 26, 2017