ForeignKeyとfilterのメモ
自己責任で
あってるか検証しようとして簡単なModelつくろうとしたけどなんかうまくいかないからメモがき
ForeignKeyは1:Nなのは知ってる
- BlogModelが1としてEntryModelがNならEntryModelにForeignKeyをはる
- この場合 blog.entrymodel_set でクエリセットがとれる
- modelを小文字で、 _set をつける。_setがついているほうがNである
filterの複合
- 普通にチェインするなら ObjModel.objects.filter(name=name).filter(user=user)とかできる
- 複合する場合は ObjModel.objects.filter(name=name, user=user)とする
- 具体的には ObjModel.objects.filter(blog__in=entry.blog_set.all(), status__in=[1,2,3]) とかする。あるblogセットかつstatusが1,2,3であるクエリセット
追記 2012/08/01
filterでチェインするところは実際にクエリを確かめたらどうも where 以下を書き換えてるだけで、「,」で区切っても同じ意味かもしれない。というか同じっぽい。pdb;pdb.set_trace()でデバッガ仕込んで、 print ObjModel.objects.filter(name='hoge').query みたいにしてやるとクエリがみれるようだ。
実例
(Pdb) print User.objects.filter(nickname='hoge', email='moge').query SELECT "User"."id", "User"."email", "User"."password", "User"."nickname", "User"."bucho_point", "User"."is_active", "User"."ctime", "User"."utime" FROM "User" WHERE ("User"."nickname" = hoge AND "User"."email" = moge ) (Pdb) print User.objects.filter(nickname='hoge').filter(email='moge').query SELECT "User"."id", "User"."email", "User"."password", "User"."nickname", "User"."bucho_point", "User"."is_active", "User"."ctime", "User"."utime" FROM "User" WHERE ("User"."nickname" = hoge AND "User"."email" = moge )
@xxxxxxxxxx
python manage.py shell でシェル起動して from django.db import connection して なんか適当にモデルインポートして知りたいクエリ実行して connection.queries 叩くとSQL見られますよ
なるほど、こういう方法もあると。
(hoge)[02:52:27 atasatamatara@dev (hg:default) ~/qa-prj]$ py manage.py shell >>> from qa.models import User >>> from django.db import connection >>> User.objects.filter(nickname='hoge', email='moge') [] >>> connection.queries [{'time': '0.002', 'sql': u'SELECT "User"."id", "User"."email", "User"."password", "User"."nickname", "User"."bucho_point", "User"."is_activ e", "User"."ctime", "User"."utime" FROM "User" WHERE ("User"."nickname" = hoge AND "User"."email" = moge ) LIMIT 21'}] >>> User.objects.filter(nickname='hoge').filter(email='moge') [] >>> connection.queries [{'time': '0.002', 'sql': u'SELECT "User"."id", "User"."email", "User"."password", "User"."nickname", "User"."bucho_point", "User"."is_activ e", "User"."ctime", "User"."utime" FROM "User" WHERE ("User"."nickname" = hoge AND "User"."email" = moge ) LIMIT 21'}, {'time': '0.000', 's ql': u'SELECT "User"."id", "User"."email", "User"."password", "User"."nickname", "User"."bucho_point", "User"."is_active", "User"."ctime", " User"."utime" FROM "User" WHERE ("User"."nickname" = hoge AND "User"."email" = moge ) LIMIT 21'}] >>> connection.queries[1] {'time': '0.000', 'sql': u'SELECT "User"."id", "User"."email", "User"."password", "User"."nickname", "User"."bucho_point", "User"."is_active ", "User"."ctime", "User"."utime" FROM "User" WHERE ("User"."nickname" = hoge AND "User"."email" = moge ) LIMIT 21'}
つまり shell しているあいだ connection が貼られていて、それを明示的に呼び出すために import して、 connection.queries で今まで発行したクエリが配列に格納されている、ということか。
参考:: http://kk6.hateblo.jp/entry/2012/08/01/Djangoの発行する生SQLが見たい
で次の話。ForeignKeyでmodel_setでとってこれるって話はあくまでインスタンスになっていることが前提っぽい(というかよく考えたら当たり前だ。インスタンスに紐付いていないものにたいしてどうクエリが発行できるのだ)。つまり上記の例で言うとあらかじめ entry という変数に Entryモデルのインスタンスをいれておくことで entry.blog_set が呼べるし、実際 entry.blog_set.all()で blog_setの中身が取れる .all() で呼んでるけど実際はクエリセットみたいなもの(実際はdjango.db.models.fields.related.RelatedManager object だ、そうだ)なので、only()とか .values() とか .order_by() とかも使える。