2017-03-29 10 views
5

私のモデルでは、私はフィールドのすべての組み合わせを書き込み、それらをフィルタリングすることなく、モデルのすべての5つのフィールド上の単一の条件を適用する簡単なクエリセットを必要とするDjangoの単一の条件に基づいて複数のフィールドをフィルタリングするクエリセットを作成するには?

class TestModel(models.Model) 
    field1 = models.IntegerField() 
    field2 = models.IntegerField() 
    field3 = models.IntegerField() 
    field4 = models.IntegerField() 
    field5 = models.IntegerField() 

です。

は、たとえば、私は2つ以上のフィールド

TestModel.objects.filter(two_or_more_fields=None) 

私は任意の2つ以上のフィールドでのクエリセットを見つけるために、5つのフィールドのすべての組み合わせを書きたくないのなしのチェックの条件を適用したいですなし。言い換えれば、よりこれを実現するためのより良い方法があります:

from django.db.models import Q 
TestModel.objects.filter(
    #condition for exactly 2 None 
    Q(field1=None & field2=None) | 
    Q(field2=None & field3=None) | 
    Q(field3=None & field4=None) | 
    Q(field4=None & field5=None) | 
    Q(field5=None & field1=None) | 
    #condition for more than 2 None 
    Q(field1=None & field2=None & field3 = None) | 
    ''''' 
    . 
    . 
    #so on to cover all possible cases of any two or more fields as None 
    ) 

が、私はこれを実現するためのより良いと簡単な方法があるはずだと思います。

答えて

3

時間を過ごした後、私は、Djangoのフィルタ構造に組み込まれて使用してこれを実行するための簡単な方法を見つけることができませんでした。このソリューションは、理由はここに使用される関数に対するPostgreSQL固有のものです

field_list = ['field1', 'field2', 'field3', 'field4', 'field5'] 

def get_all_possible_filter_dict_list_for_a_condition(field_list): 

    all_possible_filter_dict_for_a_condition = [] 
    for field_1, field_2 in combinations(field_list, 2): 
     all_possible_filter_dict_for_a_condition.append(
     { 
     field_1:None, 
     field_2:None 
     } 
     ) 
    return all_possible_filter_dict_for_a_condition 


def get_qs_list_to_perform_or_operation(all_possible_filter_dict_list_for_a_condition): 

    qs_list_to_perform_or_operation = [] 
    for i, filter_dict in enumerate(all_possible_filter_dict_list_for_a_condition): 
     qs_to_append = qs.filter(**filter_dict) 
     qs_list_to_perform_or_operation.append(qs_to_append) 
    return qs_list_to_perform_or_operation 


def get_qs_to_filter_fields_with_more_than_1_none(qs_list_to_perform_or_operation): 

    final_qs = qs_list_to_perform_or_operation [0] 
    for i in range(len(qs_list_to_perform_or_operation) - 1): 
     final_qs = final_qs | qs_list[i + 1] 
    return final_qs 

all_possible_filter_dict_list_for_a_condition 
    = get_all_possible_filter_dict_list_for_a_condition(field_list) 
qs_list_to_perform_or_operation = get_qs_list_to_perform_or_operation(all_possible_filter_dict_list_for_a_condition) 
final_qs_to_filter_multiple_fields_with_same_condtion = get_qs_to_filter_fields_with_more_than_1_none(qs_list_to_perform_or_operation) 
1

私はDjangoの非ヌルフィールドの数でフィルタリングする方法について知らないです。

私が示唆しているように、私は暗いフィールド(null_count)の数をフィールドとして格納することをお勧めします。

saveの方法をTestModelに簡単に上書きすると、これを行うことができます。

def save(self, *args, **kwargs): 
    self.null_count = 0 
    self.null_count += 1 if self.field1 is None else 0 
    # update null_count for 4 remaining fields 
    super(TestModel, self).save(*args, **kwargs) 

そして、フィルタで表示するとnull_countです。

TestModel.objects.filter(null_count_gt=2) 
+0

これは良い提案ですが、私は私の場合でモデルを変更することはできません。 – javed

0

:しかし、私は私が探していたものに近いこの解決策を見つけました。ただし、このアイデアは、別のデータベースを使用している場合に使用できます。


あなたはRawSQLの混合物といくつかのARRAY魔法を使用することができます。

アイデアがnullではないフィールドの数とクエリセット内の各項目に注釈を付けることである。

from django.db.models import Func 
from django.db.models.expressions import RawSQL 

field_list = ['field1', 'field2', 'field3', 'field4', 'field5'] 

# field1 IS NULL, field2 IS NULL, field3 IS NULL, ..... 
statements = ", ".join("{} IS NULL".format(field) for field in field_list) 

# create an array for each field by checking if those are NULL 
# then, remove the False values e.g. not null ones. 
# ARRAY_REMOVE(ARRAY[field1 IS NULL, field2 IS NULL, .....], false) 
raw_sql = "ARRAY_REMOVE(ARRAY[{statements}], false)".format(statements=statements) 

# now annotate each item with the number of null fields 
qs = TestModel.objects.annotate(num_null=Func(RawSQL(sql,()), function='CARDINALITY') 

# on this queryset you can filter by the number of null items you want to check 
qs = qs.filter(num_null__gte=2) 
+0

これはあなたのために機能しますか? – AKS

関連する問題