先週、Django 1.2が出ました。新しくて、良い機能がいっぱい入っているけども、1.1からの変更をご紹介しようかと思っています。
マルチDB
1.2では、一番大きい変更は明らかにマルチDB対応ですね。settings.py
のDATABASE
オプションはDATABASES
になりました。それでpython辞書で複数のDBを設定する。
以下のようにMySQL、sqlite、PostgreSQL、それぞれ違ってても構いません。
DATABASES = {
'default': {
'NAME': 'app_data',
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'USER': 'postgres_user',
'PASSWORD': 's3krit'
},
'users': {
'NAME': 'user_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'priv4te'
}
}
どのデータベースをどの場合に使うかをデータベースルータで決める。モデルの読み込みの場合のDB、書き込みの場合のDB、リレーションを許可するかどうか、syncdb
(テーブル定義)の許可を実装する。
class MyAppRouter(object):
"""myappアプリケーションのモデルを別DBに保存し、
DBの操作を制御する"""
def db_for_read(self, model, **hints):
"'myapp'の場合、'other'というDBを使う。"
if model._meta.app_label == 'myapp':
return 'other'
return None
def db_for_write(self, model, **hints):
"'myapp'の場合、'other'というDBを使う。"
if model._meta.app_label == 'myapp':
return 'other'
return None
def allow_relation(self, obj1, obj2, **hints):
"両方のモデルが'myapp'に入っている場合のみにリレーションを許可"
if obj1._meta.app_label == 'myapp' or obj2._meta.app_label == 'myapp':
return True
return None
def allow_syncdb(self, db, model):
"'myapp' を 'other' DB のみに入れるようにする。"
if db == 'other':
return model._meta.app_label == 'myapp'
elif model._meta.app_label == 'myapp':
return False
return None
モデル検証
モデルのデータを検証することができるようになりました。それに、新しいモジュールdjango.core.validators
ができました。フォームと同じようにfull_clean()
、clean_fields()
、clean()
、validate_unique()
の4つのメソッドが追加されました。
clean_fields(exclude=None)
を呼び出すとモデルのフィールドのデータを一個一個検証する。
clean()
はカスタム検証の処理を実装するためのメソッド。このメソッドをサブクラスで実装すれば、カスタム検証ができます。
validate_unique(exclude=None)
はユニークフィールドの検証を行う。
full_clean(exclude=None)
を呼び出すとすべての検証を行います。
exclude
パラメーターで検証を行わないフィールドを指定できる。
CSRF 対策
1.1のCsrfMiddleware
は正規表現でCSRF用フィールドをフォームに突っ込むことができたが、実装が微妙でJSなどに使えなかったので、Django 1.2でもっと綺麗なAPIが揃えました。
django.middleware.csrf.CsrfViewMiddlewareが新しくできました。このミードールウエアでCSRFのトーケンが生成され、ポストの場合、検証が行われ{% csrf_token %}
テンプレートタグでフォームに入れることができている。
Middleware
を使いたくない場合は、CSRF対策をしたいviewのみにdjango.views.decorators.csrf.csrf_protect
デコレータを使うことができます。
messages API
以前、Djangoのユーザメッセージは「変更しました」とか、「削除しました」とか、一時的なメッセージなのにデータベースに保存しましたので、微妙だった。
それで、Django 1.2では新しいmessages APIができました。DBのかわりにセキュアクッキーとセッションを使えるようになりました。後、メッセージタイプ、info、warning、errorなどが使えるようになりました。
from django.contrib import messages
messages.add_message(request, messages.INFO, 'Hello world.')
messages.success(request, u'プロフィールを更新しました。')
messages.warning(request, u'サービス契約が後3日で切ります。')
messages.error(request, u'レコードが削除されました')
メールバックエンド
クラウドサービスでは、メールがAPIで提供されているのが多くて、Django 1.1ではsend_mail
は使えなかったんですけど、Django 1.2ではメールバックエンドが使えるようになりました。
標準に入っているのは、SMTP、コンソールに出力するのみ、メールを無視するバックエンドが揃えている。
カスタムバックエンドを作るために、django.core.mail.backends.base.BaseEmailBackend
を継承して、send_messages(email_messages)
を実装する。永続コネクションを使う時はopen()
とclose()
メソッドを実装すれば良い。
smart if テンプレートタグ
Django 1.1以前では、{% if %}
テンプレートタグはbooleanしか使えなくて、複雑なコンディションが書けなかった。Django 1.2 から、==
、>
、<
、and
、or
などが使えれるようになりました。
{% if a != b %}
...
{% if c == d and e >= f %}
...
{% endif %}
...
{% endif %}
まとめ
ちょっとしたバグのため、Django 1.2.1がすぐ出ると思いますが、Django 1.2は良い新規機能が多くて、是非使って見てください。