Поиск как в админке Django

Снова привет! Осваивался с class-based views и заодно изобретал велосипед делал поиск «как в джанго-админке», то есть такой, чтобы конфигурировался максимально аналогично. Плюс, в частном случае нужно было еще ограничить поиск только «активными» документами. Вот такой маленький сниппет из этого получился:

Базовый класс, реализующий функциональность поиска

from django.db.models import Q
from django.views.generic import ListView
import itertools

class BaseSearchView(ListView):
    search_fields = []
    def get_search_fields(self):
        return self.search_fields

    query_key = 'q'
    def get_query_key(self):
        return self.query_key

    def get_query(self):
        query = self.request.GET.get(self.get_query_key(),'')
        words = [w.strip().lower() for w in query.split(' ') if w]
        or_queries = [Q(**{f + "__icontains": w}) \
            for w, f in \
            itertools.product(words, self.get_search_fields())]
        if len(or_queries) > 1:
            total_q = reduce(lambda a, b: a | b, or_queries)
        elif len(or_queries) == 1:
            total_q = or_queries[0]
        else:
            total_q = None
        return total_q

    def get_queryset(self):
        query = self.get_query()
        if query:
            result = self.model.objects.all()
        else:
            result = self.model.objects.filter(query)
        return result

Пример использования + наложение дополнительного фильтра

class DemoModelSearch(BaseSearchView):
    model = DemoModel
    search_fields = ['name','text_body','description',
                  'directory__title','name',
                  'owner__email','owner__group__name']

    def get_query(self):
        query = super(DemoModelSearch, self).get_query()
        final_query = Q(is_active__exact= True)
        if query:
            final_query &= query
        return final_query

HTML-код формы

<form action="" method="get">
    <input name="q" value="{{ request.GET.q }}" type="text">
</form>

Разумеется, все входные данные надо эскейпить и стрипить, но это уже другая история…

Сниппет на гитхабе
Надеюсь, кому-нибудь окажется полезно =)

Запись опубликована в рубрике На заметку с метками , . Добавьте в закладки постоянную ссылку.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *