2017-05-19 10 views
0

私は、ユーザが複数の年齢範囲(18-24,25-34,35-44など)でユーザを選択できるようにするフォームを持っています。現在、ユーザが最初の2つのフィールド複数の選択リストのクエリではユーザー18〜34が返されます。ユーザーが18〜24歳と35〜44歳を選択した場合、18歳から44歳までのすべての年齢が含まれます。 -34。Djangoは未知数の複数の日付範囲を照会します

ユーザーフォームの選択に先立ってフィルタリングする必要がある範囲の数を知らずに、クエリで複数の範囲フィルタを含めるアプローチはどうでしょうか?

あなたは年齢の番号範囲をユーザーがIでフィルタするつもりだった知っていた場合はこれが私の現在のクエリですQ.

を使用して、あなたは可能性がチェーンの範囲クエリを知っている:事前に

query = User.objects.filter(
      gender__in=genders, 
      created__in=dates, 
      data_source__in=sources, 
      dob__range=[dob_from, dob_to] 
     ) 

感謝。

答えて

2

ご質問のとおり、Q()オブジェクトを使用して組み合わせることができます。どのくらいの数のオブジェクトがあるかわからないということは問題ではありません。 Q()オブジェクトのリストを生成し、リストを単一のQ()に縮小します。

from operator import or_ 

# import for Python 3, not required in Python 2 
from functools import reduce 

ranges = [(18,24), (35, 44)] # hardcoded as an example, you can dynamically generate this 
qs = [Q(dob_range=[dob_from_, dob_to]) for (dob_from_, dob_to) in ranges] 
# combine the qs 
dob_q = reduce(or_, qs, Q()) 

query = User.objects.filter(
    dob_q, 
    gender__in=genders, 
    created__in=dates, 
    data_source__in=sources, 
) 

あなたはreduceor_に慣れていない場合は、リストをループで同じ結果を得ることができます。

qs = [Q(dob_range=[dob_from_, dob_to]) for (dob_from_, dob_to) in ranges] 
dob_q = Q() 
for q in qs: 
    dob_q = dob_q | q 
+0

ブリリアント!完璧に動作します。今、or_を減らして作業を減らす方法を見てみましょう。 – Theo

+0

あなたがしたくない場合は 'reduce'を使う必要はありません。リストをループして' Q() 'を生成することができます。 – Alasdair

関連する問題