基本

Django は MVC フレームワークのようですが、
コントローラ (Controller) を「ビュー (view)」と呼び、ビュー (View) を「テンプレート (template)」と呼んでいます。

djangoappengine特有

Also, never run manage.py runserver together with other management commands at the same time. The changes won't take effect. 

manage.py deploy uploads your project to App Engine (use this instead of appcfg.py update)

Many advanced Django features are not supported at the moment. A few of them are:
    transactions (but you can use run_in_transaction() from App Engine's SDK)

トランザクション内でのクエリー

できない。行うとこういう例外になる。
BadRequestError: Only ancestor queries are allowed inside transactions. 

主キーでの検索は可能。
たぶん、主キーでの検索は内部的にdb.get(key)に変換されている。

そのため、トランザクションでget_or_createをしたい場合は、
クエリーせずに主キーを知るために、自分で主キーを生成する必要がある。

def generate_primary_key(str):
    return hashlib.sha1(str.encode('utf-8')).hexdigest()

Person.objects.get_or_create(
    pk = generate_primary_key(name), ...
みたいな感じ。

自動付番だと主キーを知るにはクエリーしないといけない。
けどトランザクション内ではできないし、外で行うとアトミックな操作ではなくなってしまう。

リレーションでの、暗黙のgetに注意

こういうことをすると、リレーション先のpersonを1個ずつgetするのでとても遅い
pictures = Picture.objects.filter(...)
[ e for e in pictures if e.person == None ]

nullチェックしたいだけなら、こうするとずっと速い

[ e for e in pictures if e.person_id == None ]

内部動作は、appengine-profilerのDatastoreProfilerで確認できる。
上記だとpicturesの取得はRunQueryだった(= batch get)なのでたぶん大丈夫

select_related() も試したけど効かなかった。
内部でbatch getはしてくれないみたい。

管理サイト

管理者アカウント作成
$ ./manage.py createsuperuser

リモートでも同様に

$ ./manage.py remote createsuperuser

コードの変更は下記に従う。
http://docs.djangoproject.com/en/1.2/intro/tutorial02/

日本語版ドキュメント(1.0)の手順は古いので注意。
特に、

admin.site.register(Person)
の記述をmodels.pyで行うと、なぜかリモートのみ管理画面が動かなくなる。
admin.pyで行うこと。
(admin.pyで行うと、Authモジュールのレコードが表示されなくなる。謎)

GAEのランチャーから起動したサーバだと、なぜかログインできないので
http://groups.google.com/group/django-non-relational/browse_thread/thread/ee2bdfa025e7d88a

こっちのサーバを使う

$ ./manage.py runserver

ユーザ管理

$ ./manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.all()
[<User: nickle>]
>>> User.objects.all()[0]
<User: nickle>
>>> User.objects.all()[0].password
(snip)
>>> User.objects.all()[0].is_active
True
>>> User.objects.all()[0].is_staff
True
>>>

デバッグ

どんなSQLに落ちてるか確認する

サーバを -d で立ち上げ、クエリー後にどっかでこれを実行
import logging
from django.db import connection
logger = logging.getLogger()
logger.debug(connection.queries)

Tips

  • get_object_or_404