Сайт Игоря Кононученко   Статьи

Динамические запросы (фильтры) в django

4 июня 2008

Хороший заголовок, информации в гугле по этому поводу не найдено. Стоит задача сделать фильтр. Возьмем, к примеру, таблицу, первая строка которой содержит фильтры для колонок. Усложненный вариант фильтра позволяет выбирать сразу несколько значений. Реализовать такой механизм средствами ORM django довольно просто.

Создаем метод, получающий на вход имя поля и массив значений:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from django.db.models import Q
# тут происходит or соединение условий
def _get_condition(self, field, values):
        result = None
        for value in values:
            query = Q(**{str(field): str(value)})
            if not result:#for first value
                result = query
            else:
                result = result | query
        return result

# тут происходит and соединение условий
 def _get_filtering_param(self, filters):
        result = None
        for field, values in filters.items():
                condition = self._get_condition(field, values)
                if not result:#for first value
                    result = condition
                else:
                    result = result & condition
       
        return result
Вызывать можно таким образом:
1
2
3
4
5
condition = self._get_filtering_param(
{"city__country__name", ["Ukraine", "Russua"], "title": ["Wow"]}
)
query = self.model.objects.filter(condition)
#print query.query.as_sql() - при желании можем посмотреть, сгенерированный sql
Обращаю внимание на одну очень замечательную особенность ORM django — city__country__name. Эта запись означает, что мы фильтруем по имени страны, к которой принадлежит город нашей целевой модели. Работу по созданию джоинов джанго берет на себя.

Основываясь на коде, приведенном выше можно построить универсальную систему фильтрации.

Template из Prototype.js на C# 3.0
Python yield — простым языком
Ctrl
Симметрия кода
Значение поля формы в Django-шаблоне