最近困ったこととか、気付いたことのメモ
久しぶりに django をいじってるせいか、ちょくちょく詰まる。それも、「あれ、前にもここで詰まったような・・・」っていうのが多い。解決できたかどうかも覚えてない。
これはいささかDRY原則の侵犯であると言わざるを得ないので、思いつくままにメモしておく。
モデル定義で文字列の扱いが統一されてない?
validate に失敗して初めて気付いた。unicodeブランチがマージされたので、__unicode__メソッドで unicode を返すように気を付けてたんだけど、あるとき UnicodeDecodeError が発生した。原因は、フィールド定義で verbose_name に unicode を使ってなかったから。
気付くのに手間取ったので、モデル内を全部 unicode にしてみた。今度は list_display でエラーが発生する。こいつは str じゃないとダメみたい。ちょっと分かりにくいなあ。
validate時にDBをチェックしたいけど・・・
django の管理サイトはステキすぎなので、全力でこれを利用したいわけです。でも、ちょっと複雑な validate をやるとすぐ困る。例えば、DB上にレコードが1個しか存在しないモデルを定義したら、2個目を生成するのは阻止したい。モデルのフィールドに validator_list を定義するのはなんか違う気がする。じゃあ save メソッドをオーバーライドして、ValidationError を投げればいいだろう、と毎回考える。ところがこの方法だと、 Error がキャッチされずに Traceback が表示される。レコードの追加は阻止できてるのでOKなんだけど、うまい方法が思いつかない。
カスタム validator と edit_inline は相性が悪い?
ちょっと上のと関係あり。たとえばこんなモデルがあったとして、
class Parent(models.Model): # フィールドを定義 class Child(models.Model): parent = models.ForeignKey(Parent, edit_inline=models.STACKED) other = models.CharField('dummy', validator_list=[custom_validator])
このとき管理サイトで Parent を編集すると、Childもいくつか編集できる。その Child を validate しようとして困った。カスタム validator に渡されるパラメータ、field_data はまあいいとして、all_data は Parent のデータ+Childすべてのデータが入った辞書だ。自分が対象とすべきデータがさっぱり分からないので、validate しようがない。edit_inline 使うなってことか。
テンプレートフォルダは各アプリの直下に置いた方が楽
昔はプロジェクトフォルダの下に templates フォルダを作って、その下に各アプリの名前を持つテンプレート置場を用意してた。この方法だと settings.py にその場所を指定しないといけない。
それに対して、各アプリの下に templates フォルダを作成しておくと、何もしていしなくても探しに行ってくれる。ルースカップリングの点からもこちらの方が全然便利だ。
django のテンプレートは ajax と相性がいい
ajax でページの一部分を変更する、とかがすごい楽。たとえば hoge.html がこんなだった場合、
{% extends "base.html" %} {% block contents %} 前半 {% include "hoge_body.html" %} 後半 {% endblock %}
ビューではこう書けばいい。
def view(request): if 'ajax' in request.GET: return render_to_response('hoge_body.html') else: return render_to_response('hoge.html')
JSONで返したければ、HttpResponse を使えばいい。Javaとか.NETだとこんなに簡単じゃないんだろうな・・・
開発中は管理者ユーザを Fixture に入れておくと楽
頻繁にモデルを修正してると、管理者ユーザの作成が面倒臭い。大した手間ではないんだけど、メールアドレスとかちゃんと入れないとダメなので困る。
なので管理者ユーザを作成した状態で、データをダンプしておく。
python manage.py dumpdata --format=xml --indent=2 > initial_data.xml
不要なデータを削除したら、initial_data.xml をプロジェクトルートか、各アプリの Fixtures フォルダに置いておく。あとは syncdb したときに、管理者ユーザの作成をスキップすればいい。