アプリをDjango0.96から1.0に移植する—Djangoのドキュメント
アプリをDjango0.96から1.0に移植する
Django 1.0は、一部の領域で0.96との互換性を失います。
このガイドは、0.96のプロジェクトとアプリを1.0に移植するのに役立ちます。 このドキュメントの最初の部分には、1.0で実行するために必要な一般的な変更が含まれています。 最初の部分を実行してもコードが壊れてしまう場合は、あまり一般的でない変更のセクションで、あまり一般的でない互換性の問題のリストを確認してください。
一般的な変更
このセクションでは、ほとんどのユーザーが行う必要のある0.96と1.0の間の変更について説明します。
Unicodeを使用する
文字列リテラル('foo'
)をUnicodeリテラル(u'foo'
)に変更します。 Djangoは全体でUnicode文字列を使用するようになりました。 ほとんどの場所で、生の文字列は引き続き機能しますが、Unicodeリテラルを使用するように更新すると、いくつかのあいまいな問題を防ぐことができます。
詳細については、 Unicodeデータを参照してください。
モデル
モデルファイルへの一般的な変更:
maxlengthの名前をmax_lengthに変更します
maxlength
引数の名前をmax_length
に変更します(これはフォームフィールドと一致するように変更されました)。
__str__を__unicode__に置き換えます
モデルの__str__
関数を__unicode__
メソッドに置き換え、そのメソッドで Unicode (u'foo'
)を使用していることを確認してください。
prepopulated_fromを削除します
モデルフィールドのprepopulated_from
引数を削除します。 無効になり、admin.py
のModelAdmin
クラスに移動されました。 管理者への変更の詳細については、以下の管理者を参照してください。
coreを削除します
モデルフィールドからcore
引数を削除します。 同等の機能(インライン編集の一部)が管理インターフェースによって異なる方法で処理されるようになったため、これは不要になりました。 以下の admin セクションに到達するまで、インライン編集について心配する必要はありません。 今のところ、core
へのすべての参照を削除します。
class Admin:をadmin.pyに置き換えます
モデルからすべての内部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 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での最大の変更点の1つは、新しい管理者です。 Django管理インターフェース(django.contrib.admin
)は完全にリファクタリングされました。 管理者定義はモデル定義から完全に分離され、フレームワークはDjangoの新しいフォーム処理ライブラリを使用するように書き直され、拡張性とカスタマイズを念頭に置いて再設計されました。
実際には、これはすべてのclass Admin
宣言を書き直す必要があることを意味します。 上記のモデルで、[X105X] を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'}),
)
も参照してください
- 変更とその背後にある理由の詳細については、 NewformsAdminBranchwikiページを参照してください。
- 新しい管理者には、たくさんの新機能が付属しています。 それらについては、管理ドキュメントで読むことができます。
URL
ルートを更新する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 ...
)
ビュー
newformsの代わりにdjango.formsを使用してください
django.newforms
をdjango.forms
に置き換えます– Django1.0はnewforms
モジュール(0.96で導入)の名前をプレーンな古いforms
に変更しました。 oldforms
モジュールも削除されました。
すでにnewforms
ライブラリを使用していて、推奨されるimport
ステートメント構文を使用している場合は、インポートステートメントを変更するだけです。
年:
from django import newforms as forms
新しい:
from django import forms
古いフォームシステム(以前はdjango.forms
およびdjango.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を使用してファイルフィールドを操作する
django.db.models.FileField の内部実装が変更されました。 これの目に見える結果は、これらのモデルフィールドの特別な属性(URL、ファイル名、画像サイズなど)にアクセスする方法が変更されたことです。 モデルの 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
|
width
およびheight
属性は、 ImageField フィールドに対してのみ意味があることに注意してください。 詳細については、モデルAPI のドキュメントをご覧ください。
ObjectPaginatorの代わりにPaginatorを使用してください
0.96のObjectPaginator
は削除され、改善されたバージョン django.core.paginator.Paginator に置き換えられました。
テンプレート
自動エスケープを愛することを学ぶ
デフォルトでは、テンプレートシステムはすべての変数の出力を自動的にHTMLエスケープするようになりました。 詳細については、自動HTMLエスケープを参照してください。
個々の変数の自動エスケープを無効にするには、:tfilter: `safe` フィルターを使用します。
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
テンプレート全体の自動エスケープを無効にするには、テンプレート(またはテンプレートの特定のセクションのみ)を:ttag: `autoescape` タグでラップします。
{% autoescape off %}
... unescaped template content here ...
{% endautoescape %}
あまり一般的ではない変更
次の変更は、より小さく、よりローカライズされた変更です。 これらは上級ユーザーにのみ影響するはずですが、リストを読んでコードでこれらのことを確認することはおそらく価値があります。
信号
- 登録済みのシグナルハンドラーに
**kwargs
を追加します。 django.dispatch.dispatcher
のモジュールメソッドではなく、 Signal オブジェクトのメソッドを介して信号を接続、切断、および送信します。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.contrib.localflavor.usa
はdjango.contrib.localflavor.us
に名前が変更されました。 この変更は、他のローカルフレーバーの命名スキームと一致するように行われました。 コードを移行するには、インポートを変更するだけです。
セッション
新しいセッションキーの取得
SessionBase.get_new_session_key()
は_get_new_session_key()
に名前が変更されました。 get_new_session_object()
はもう存在しません。
備品
行をロードしてもsave()が呼び出されなくなりました
以前は、行をロードすると、モデルのsave()
メソッドが自動的に実行されていました。 これはもはや当てはまらないため、save()
によって自動入力されたフィールド(タイムスタンプなど)には、フィクスチャに明示的な値が必要になります。
設定
より良い例外
古いEnvironmentError
は、Djangoが設定モジュールを見つけられなかったときにImportError
に分割され、すでに使用した後で設定を再構成しようとするとRuntimeError
に分割されました。
:setting: `LOGIN_URL` が移動しました
:setting: `LOGIN_URL` 定数がdjango.contrib.auth
からsettings
モジュールに移動しました。 使用する代わりにfrom django.contrib.auth import LOGIN_URL
参照する :setting: `settings.LOGIN_URL ` 。
:setting: `APPEND_SLASH` の動作が更新されました
0.96では、URLがスラッシュで終わっていないか、パスの最後のコンポーネントにピリオドがあり、:setting: `APPEND_SLASH` がTrueの場合、Djangoは同じURLにリダイレクトしますが、末尾にスラッシュが追加されています。 これで、Djangoは、末尾にスラッシュがないパターンがURLパターン内の何かと一致するかどうかを確認します。 その場合、意図的にそのパターンをキャッチしたいと想定されているため、リダイレクトは行われません。
ほとんどの人にとって、これは変更を必要としません。 ただし、次のようなURLパターンを持っている人もいます。
r'/some_prefix/(.*)$'
以前は、これらのパターンは、末尾にスラッシュがあるようにリダイレクトされていました。 このような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(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.0):
class MyModel(models.Model):
field_name = models.DecimalField(max_digits=10, decimal_places=3)
...
この変更を忘れると、__init__
のmax_digits
属性を取得しないFloatField
に関するエラーが表示されます。これは、新しいFloatField
が精度をとらないためです-関連する引数。
MySQLまたはPostgreSQLを使用している場合、それ以上の変更は必要ありません。 DecimalField
のデータベース列タイプは、古いFloatField
の場合と同じです。
SQLiteを使用している場合は、データベースに適切な列を浮動小数点ではなく10進型として表示させる必要があります。 これを行うには、データをリロードする必要があります。 コードでDecimalField
を使用するように変更し、Djangoコードを更新した後で、これを行います。
警告
最初にデータベースをバックアップしてください!
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
ノート:
- このプロセスの最初のステップでは、XML形式を使用することを忘れないでください。 SQLiteを使用してfloatを10進数に移植できるようにするXMLデータダンプの機能を活用しています。
- 2番目のステップでは、問題のアプリケーションのデータを失う準備ができていることを確認するように求められます。 イエスと言う; もちろん、このデータは3番目のステップで復元します。
DecimalField
は、この変更が行われる前にDjangoに同梱されていたアプリでは使用されていないため、標準のDjangoモデルでこの手順を実行することを心配する必要はありません。
上記のプロセスで問題が発生した場合は、バックアップしたデータベースファイルを元のファイルにコピーして、最初からやり直してください。
国際化
django.views.i18n.set_language()でPOSTリクエストが必要になりました
以前は、GETリクエストが使用されていました。 古い動作は、状態(サイトの表示に使用されるロケール)がGETリクエストによって変更される可能性があることを意味していました。これは、HTTP仕様の推奨事項に反しています。 このビューを呼び出すコードは、GETではなくPOSTリクエストが行われるようにする必要があります。 つまり、リンクを使用してビューにアクセスすることはできなくなりますが、何らかのフォーム送信を使用する必要があります(例: ボタン)。
_()は組み込みではなくなりました
_()
(名前が単一のアンダースコアである呼び出し可能オブジェクト)は、組み込みにモンキーパッチされなくなりました。つまり、すべてのモジュールで魔法のように利用できなくなりました。
以前は_()
が常に存在することに依存していた場合は、必要に応じてugettext
またはugettext_lazy
を明示的にインポートし、自分で_
にエイリアスする必要があります。
from django.utils.translation import ugettext as _
HTTP要求/応答オブジェクト
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.headers:
の代わりにif header in response:
を使用してください。
一般的な関係
一般的な関係はコアから移動されました
汎用リレーションクラス– 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.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
データ構造
SortedDictFromListはなくなりました
django.newforms.forms.SortedDictFromList
は削除されました。 django.utils.datastructures.SortedDict
は、タプルのシーケンスでインスタンス化できるようになりました。
コードを更新するには:
django.newforms.forms.SortedDictFromList
を使用していた場所では、django.utils.datastructures.SortedDict
を使用してください。django.utils.datastructures.SortedDict.copy
はSortedDictFromList.copy()
のようにディープコピーを返さないため、ディープコピーに依存している場合はコードを更新する必要があります。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
|
コメント
Django0.96の
django.contrib.comments
アプリを使用していた場合は、1.0で導入された新しいコメントアプリにアップグレードする必要があります。 詳細については、アップグレードガイドを参照してください。