私がDjangoのORMを気に入っているのは、Pythonコードでスマートにクエリセットを作れるからです。
例を書いてみる。
blog/models.py
from django.db import models import datetime class Entry(models.Model): title = models.CharField(max_length=100) content = models.TextField() create_date = models.DateTimeField(default=datetime.datetime.now) def __unicode__(self): return self.title
こんなモデルを作った。
Qオブジェクトを使ってクエリセットを作ってみる
In [1]: from blog.models import Entry In [2]: Entry.objects.create(title='hoge', content='foo') Out[2]: <Entry: hoge> In [3]: Entry.objects.create(title='fuga', content='bar') Out[3]: <Entry: fuga> In [4]: Entry.objects.create(title='fizz', content='buzz') Out[4]: <Entry: fizz>
まずは"manage.py shell"でtitleが"hoge"、"fuga"、"fizz"でcontentが"foo"、"bar"、"buzz"のデータを作っておきます。
複雑な照合はQオブジェクトを使うと簡単にできます。reduce*1でQオブジェクトを結合するつもりなのでoperatorもインポートしておきます。
In [5]: from django.db.models import Q In [6]: import operator
よくある検索のパターンですが、"hoge fuga"という文字列からtitleが"hoge"または"fuga"であるクエリセットを得てみます。
In [7]: Entry.objects.filter(reduce(operator.or_, [Q(title=keyword) for keyword in "hoge fuga".split(' ')])) Out[7]: [<Entry: hoge>, <Entry: fuga>]
"hoge fuga"をsplitで分解してkeywordに入れ、Qオブジェクトにしたものをリストにし、Qオブジェクトをor演算でつなげてfilterに渡します。
DjangoのQオブジェクトはこのように通常のPythonの演算子で結合できるので、さらに複雑な条件でも簡単に作成することができます。
titleの先頭が"fi"もしくは、titleかcontentに"o"を含むクエリセットを得てみます。
In [10]: Entry.objects.filter(Q(title__startswith='fi') | Q(title__contains='o') | Q(content__contains='o')) Out[10]: [<Entry: hoge>, <Entry: fizz>]
このような複雑なクエリでもSQLの知識なしに簡単に扱えます。すばらしい。