DjangoのORマッパーでSQL文を簡単に出力するサンプル
この記事でDjangoのORMapperをちょっと試そうとしてうまくいかなかったって話があったけど、簡単にDjangoが出力するSQL文を見たいときはどうしたらいいのかな?
# -*- coding:utf-8 -*- from django.db import models class Bread(models.Model): class Meta: db_table = "bread" app_label = "sample" name = models.CharField(max_length=255) price = models.IntegerField() class BreadStore(models.Model): class Meta: db_table = "bread_store" app_label = "sample" bread = models.ForeignKey(Bread) name = models.CharField(max_length=255) def main(): print BreadStore.objects.filter(bread__name="foo").query if __name__ == "__main__": main()
実行結果
$ PYTHONPATH=.:foo DJANGO_SETTINGS_MODULE=foo.settings python foo/sample.py SELECT `bread_store`.`id`, `bread_store`.`bread_id`, `bread_store`.`name` FROM `bread_store` INNER JOIN `bread` ON (`bread_store`.`bread_id` = `bread`.`id`) WHERE `bread`.`name` = foo
QuerySet.queryからSQL文を見られる
上のコードの通り、QuerySet.queryをprintするとSQL文が見られる。
DjangoのORMapperを使ったときにどういうクエリが発行されるのか簡単に調べたいときは重宝する。
ちょっと試しのときはMetaのapp_labelを忘れないこと
上のコードのMetaって内部クラスを見るとapp_labelって属性を定義している。
これがないとこういうエラーになって動かない。
Traceback (most recent call last):
File "foo/sample.py", line 5, in
class Bread(models.Model):
File "/home/psappho/.virtualenvs/django/local/lib/python2.7/site-packages/django/db/models/base.py", line 54, in __new__
kwargs = {"app_label": model_module.__name__.split('.')[-2]}
IndexError: list index out of range
app_labelを書いておけば大丈夫。
models.pyをパッケージにしてモデル定義を分割したいときもMeta.app_labelが使える
Djangoのモデル定義は基本的にDjangoアプリのパッケージのmodels.pyに書いておかないとsyncdbの対象とかにならない。
何でなのかわかんないけど、"models"ってモジュールに書いてあることをわざわざ見ている。
だからmodels.pyに沢山モデルのコードを書いてしまって長くなった場合に、いくつかのモデル定義ごとにファイルを分割したくなるけど、何もしないとsyncdbの対象とかにならない。
例えば
app └foo └models └spam └ham └egg
こういう風にmodelsをパッケージにしてspam, ham, eggにモデル定義を分割したい場合はMeta.app_labelを付けておくこと。
[app/foo/models/spam.py]
from django.db import models class Spam(models.Model): class Meta: db_table = "spam" app_label = "foo" name = models.CharField(max_length=255)
[app/foo/models/__init__.py]
from app.foo.models.spam import Spam
追記: django.db.connection.queriesを見る方法について
Djangoの発行する生SQLが見たい - PYTHONIC BOOM BOOM HEAD
ボクの記事を見てconnection.queriesを見る方法もあるよって教えてくれた人がいました。
ただ、この方法はボクもこれは知っていたんですけど、これは本当にデータベースに流したSQLを後から確認する方法なので、対象テーブルが存在しないと実行できません。
あと、あんまり気にしなくていいけど、settings.DEBUG=Trueじゃないと見られません。
pdbとか対話型インタプリタでQuerySetに特定の操作をするとどういうクエリを出力するのか確認したいときは、QuerySet.queryをプリントするのが手軽かなーと思います。
この記事を書いていて気づいたんですけど、app_labelをつけるとかいう話は重要ではなかったですね(汗)
一番推したかったことはQuerySet.queryをプリントするってところでした。
レスをくれたaltnightさん、kk6さんに感謝です。