痛風とシステム障害を恐れるエンジニアのブログ

趣味のことだったり仕事に関することだったりを徒然なるままに。webとかオープン系の会社で働いてます。お仕事の依頼お待ちしておりまーす。

DjangoのORMのFilterを動的に作りますよっと。

今作ってるサイトの要件の中で、ユーザが任意に入力した言葉を元に検索するというのを実装しようと思ったのがことの発端。

基本的にはURIのパラメーターを元に定型的な検索をする仕組みで作っていて、そのための情報がわんさかあったのですが、
パラメーターを動的に構築するのは少し手間がかかったのでメモっておきます。


要件をもう少し噛み砕くと、TextInputに入力された単語でDBの任意の列を検索します。
TextInputに複数の単語を入力するときはスペース区切りで行います。
というのが前提。

通常の検索処理は

Articles.objects.filter(id=1)

といった形で書いてます。

今回の動的にフィルターを構築するぱてぃーんが↓のような感じです。

from django.db.models import Q

q = request.POST['q']
words = q.split()
queries = [Q(contents__contains=word) for word in words]
query = queries.pop()
for item in queries:
   query |= item
rows = Articles.objects.filter(query)

まずはQオブジェクトのインポートを行っています。
そしてPOSTで送られてきたqパラメータの中身をスペースで区切っています。

 (contents__contains=word)

この記述はSQL的に言うと

contents like '%{word}%'

になるようです。と、これを書いてて気づいたのですが、文字の大小は区別して検索するようです。
ちょっと対策を考えないといけないかも/(^o^)\

words = q.split()

この部分でスペースで文字を区切ってるんですが、引数に何も指定しなくてもやってくれるので素晴らしいですね。


以上です。
参考にしたサイトは↓こちら。stackoverflow.com