Как не учитывать поле фильтра django, если поле пустое? - PullRequest
0 голосов
/ 29 января 2020

Итак, я начал кодировать систему фильтрации для моего django приложения. Это выглядит так:

class Person(models.Model):
     first_name = models.CharField(max_length = 50)
     middle_name = models.CharField(max_length = 50)
     last_name = models.CharField(max_length = 50)

Я хотел отфильтровать, у какого Person есть поле, содержащее значение x, если другие поля пусты, как этот алгоритм

results = Person.objects.filter(first_name__contains = "a")

, но если другие поля не пустые, я хочу отфильтровать это так

results = Person.objects.filter(first_name__contains = "a", middle_name__contains = "a", last_name__contains = "a")

в зависимости от того, какие поля не имеют пустых значений.

моя первая попытка была такой:

if first_name != "":
     results = Person.objects.filter(first_name__contains = first_name)
if middle_name != "":
     results = results.filter(middle_name__contains = middle_name)
if last_name != "":
     results = results.filter(last_name__contains = last_name)

Моя проблема здесь заключается в том, что он фильтрует его последовательно, поэтому, если я отфильтрую только middle_name или last_name, он выдаст мне ошибку, поскольку results еще не определен, может ли кто-нибудь помочь мне с этим?

Есть ли алгоритм, который идет так? results = Person.objects.filter(first_name__contains = first_name if first_name != "" else JUST REMOVE THIS FILTER)? потому что, если он фильтрует "", он вернет все ваши данные. Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 29 января 2020

Вы можете создать набор запросов поэтапно

qs = Person.objects.all()
if first_name != "":
   qs = qs.filter( first_name__contains=first_name )
if middle_name != "":
   qs = qs.filter( middle_name__contains=middle_name )
if last_name != "":
   qs = qs.filter( last_name__contains=last_name )

Вы можете сделать то же самое с объектами Q для сопоставления типа OR (это немного сложнее)

qs = Person.objects.all()
q = None
for op, name in (( "first_name__contains", first_name),
                 ( "middle_name__contains", middle_name),
                 ( "last_name__contains",  last_name)) :

    if name != "":
        if q:
            q = q | Q( **{ op: name} )
        else
            q =     Q( **{ op: name} )

if q:
    qs = qs.filter(q)
0 голосов
/ 29 января 2020

Проще говоря, вы хотите сделать OR между first_name, last_name и middle_name, когда запрашиваете указанную c предоставленную строку.

Я настоятельно рекомендую Вы используете Поиск объектов Q в Django

Ваш код будет проще, как показано ниже:

text = 'a'
results = Person.objects.filter(Q(first_name__contains=text) | Q(middle_name__contains=text) | Q(last_name__contains=text))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...