Использование "django-filter" с полем CHOICES - нужна опция "Любой". Django фильтр


Django – фильтрация данных на сайте

 

Если вы новичёк в django, ознакомьтесь сначала с данной статьей  "Как создать сайт на django"

 

Фильтрация делается с помощью форм.

Для этого в приложении нужно создать файл forms.py

 

 

И записать в нём следующее:

 

1. Импортируем модуль forms:  from django import forms

2. Создаём класс ArticlesFilterForm (Articles – наша модель):

 

 

 

Прописываем в нём min_price и max_price, что означает минимальная и максимальная цена. Переменные принимают модуль forms с классом IntegerField.

 

3. Теперь в файле home.html добавим в блок content форму , которая будет возвращать  {{ form.as_p }}

 

 

4. В файле views.py импортируем наш класс, в котором прежде прописали форму: from .forms import ArticlesFilterForm

 

И как показано на картинке, в context который возвращает содержимое на страницу home (то есть главную)надо добавить форму,  присваиваем переменной form класс, который мы импортировали, и добавляем переменную в context.

В аргументы класса ArticlesFilterForm добавили request.GET, для того чтобы сохранить в форме значения, после того как нажали на поиск (Search)

 

4. Перейдём на сайт, и увидим что у нас появилась форма

 

 

5. Попробуем набрать значения и нажмём Search

 

Увидим, что url получил аргументы  ?min_price=50&max_price=100 и в форме сохранились значения.

 

 

 

6. Для того, чтобы фильтер работал в метод home нужно добавить несколько строчек:

 

if form.is_valid(): — проверяем если данные формы валидны

 

if form.cleaned_data["min_price"]: - данные формы помещаются в cleaned_data, проверяем если есть там min_price,если есть то отфильтровываем articles.filter(price__gte=form.cleaned_data["min_price"]), price__gte – означает больше или равно, то есть в переменную articles запишутся данные, которые будут равны или будут больше минимальной цены min_price.

 

if form.cleaned_data["max_price"]: — данные формы помещаются в cleaned_data, проверяем если есть там max_price, если есть то отфильтровываем articles.filter(price__lte=form.cleaned_data["max_price"]), price__lte – означает меньше или равно, то есть в переменную articles запишутся данные, которые будут равны или будут меньше максимальной цены max_price.

 

 

Теперь наш фильтр работает и поиск нам выдаёт желаемый результат.

 

ДОПОЛНИТЕЛЬНАЯ ВОЗМОЖНОСТЬ АДМИН ПАНЕЛИ:

Допустим мы хотим добавить фильтрацию для наших статей в админ панели, и мы хотим фильтровать по дате.Сделать это очень легко, просто добавить в admin.py приложения в класс AdminArticle: list_filter = ["date"]И увидим колонку FILTER в правом углу экрана.

 

 

 

Источник:

https://www.youtube.com/watch?v=4qPpXinUhIw

 

Также в django можно сортировать данные (например вывести все статьи по алфавиту), подробнее "Сортировка данных в Django"

 

 

 

 

 

ПОНРАВИЛАСЬ СТАТЬЯ? ПОДПИСЫВАЙТЕСЬ НА ОБНОВЛЕНИЯ И ДЕЛИТЕСЬ С ДРУЗЬЯМИ :)

vikks-weblog.com

django - Использование "django-filter" с полем CHOICES - нужна опция "Любой"

Как упоминалось в коротких, но сладких документах "использования",

Фильтры также принимают любые произвольные аргументы ключевых слов, которые передаются на django.forms.Field.

Это не имело большого смысла, пока я не посмотрел немного дальше. В каталоге ./django-filter/docs/ref/ есть filters.txt, который описывает поля фильтра и какие поля модели они взаимодействуют по умолчанию. (Я думаю, что у меня есть язык здесь, если нет, поправьте меня).

Итак, мы видим, что ChoiceFilter используется для любого поля "с выбором".

Подхватывая документацию Django, что важно здесь, это поля формы, и как они взаимодействуют с моделями. (Использование Django Forms). Итак, мы находим ChoiceField (http://docs.djangoproject.com/en/dev/ref/forms/fields/#choicefield), в котором говорится

Принимает один дополнительный необходимый аргумент: ChoiceField.choices   Итерируемый (например, список или кортеж) двухкортежей для использования в качестве выбора для этого поля.

Итак, вы можете передать ему список, а не только исходный набор Tuple.

Итак, это может быть не pythonic или DRY, но вот как я изменил рассматриваемую модель:

class TicketFilter(django_filters.FilterSet): class Meta: model = Ticket fields = ['assigned_to', 'priority', 'status'] def __init__(self, *args, **kwargs): super(TicketFilter, self).__init__(*args, **kwargs) self.filters['priority'].extra.update( { 'choices': CHOICES_FOR_PRIORITY_FILTER })

И выше того, где были определены мои _CHOICES, я определил этот новый (упомянутый выше) и обязательно добавил исходные варианты до конца:

CHOICES_FOR_PRIORITY_FILTER = [ ('', 'Any'), ] CHOICES_FOR_PRIORITY_FILTER.extend(list(TICKET_PRIORITY_CHOICES))

Я использую list() здесь, потому что исходные варианты были установлены в кортеже, поэтому я хочу превратить это в список. Кроме того, если вы получаете ошибку NoneType, убедитесь, что вы не пытаетесь присвоить "возвращаемое значение" .extend(), потому что его нет. Я споткнулся об этом, потому что забыл, что это метод list, а не функция, которая вернула новый список.

Если вы знаете более простой, более суровый или "питонический" способ сделать это, пожалуйста, дайте мне знать!

qaru.site

django - Как фильтровать таблицы с помощью общих представлений Django?

С проб и ошибок и некоторыми предложениями Николаса Каттлера я смог получить его пример. Я немного исказил его пример, но, похоже, он близок к минимальному количеству кода, необходимого в Django, чтобы иметь общую страницу просмотра списка на основе класса с сортировкой, фильтрацией (и, следовательно, поиском) и разбиением на страницы, и я Не думаю, что это нарушает (тоже m) любые методы кодирования Django. Вот весь необходимый код:

models.py (никаких изменений в вопросе)

from django.db import models class Author(models.Model): name = models.CharField(max_length=100)

И небольшое изменение в tables.py в вопросе:

import django_tables2 as dt2 from .models import Author class AuthorTable(dt2.Table): class Meta: model = Author attrs = {"class": "paleblue"} per_page = 30

filters.py (никаких изменений в вопросе)

import django_filters as df from .models import Author class AuthorFilter(df.FilterSet): class Meta: model = Author

forms.py. Я не мог понять, как/где получить форму submit button из django_filters в сочетании со всем остальным, поэтому этот код подавляет теги обертки формы от хрустящей, а затем мы предоставляем этот HTML-код в шаблоне, что, вероятно, является kludgiest часть этого.

from django import forms from .models import Author from crispy_forms.helper import FormHelper class AuthorListFormHelper(FormHelper): model = Author form_tag = False

Я переместил вспомогательную функцию из view.py в отдельный файл и должен был удалить код разбивки на страницы, чтобы предотвратить ошибку (хотя разбиение на страницы все еще работает). Итак,

utils.py

from django_tables2 import SingleTableView from django_tables2.config import RequestConfig class PagedFilteredTableView(SingleTableView): filter_class = None formhelper_class = None context_filter_name = 'filter' def get_queryset(self, **kwargs): qs = super(PagedFilteredTableView, self).get_queryset() self.filter = self.filter_class(self.request.GET, queryset=qs) self.filter.form.helper = self.formhelper_class() return self.filter.qs def get_context_data(self, **kwargs): context = super(PagedFilteredTableView, self).get_context_data() context[self.context_filter_name] = self.filter return context

Вместо views.py в этом вопросе views.py:

from .models import Author from .tables import AuthorTable from .filters import AuthorListFilter from .forms import AuthorListFormHelper from utils import PagedFilteredTableView class AuthorList(PagedFilteredTableView): model = Author table_class = AuthorTable filter_class = AuthorListFilter formhelper_class = AuthorListFormHelper

И этот шаблон:

author_list.html (имя явно не указано нигде, потому что оно подразумевается моделью в представлении, я думаю)

{% extends "base.html" %} {% load render_table from django_tables2 %} {% load crispy_forms_tags %} {% block content %} {% render_table table %} <hr/> <form action="" method="get"> {% crispy filter.form filter.form.helper %} <input type="submit" value="Filter"/> </form> {% endblock content %}

И, для полноты, строка в urls.py:

... url(r'^$', views.AuthorTableList.as_view(), name='author_table'), ...

И вы должны иметь пакеты django-tables2, django-filters и crispy-forms, установленные и настроенные в соответствии с их инструкциями. Единственное, что меня смутило, было то, что я как-то с первой попытки пропустил, что мне это нужно в settings.py:

CRISPY_TEMPLATE_PACK = 'bootstrap'

Все это для Django 1.6.

qaru.site

python - Django filter queryset __in для * каждого * элемента в списке

Резюме:

Один из вариантов, как было предложено jpic и sgallen в комментариях, добавить .filter() для каждой категории. Каждый дополнительный filter добавляет больше объединений, что не должно быть проблемой для небольшого набора категорий.

Существует aggregation подход. Этот запрос будет короче и, возможно, быстрее для большого набора категорий.

У вас также есть возможность использовать пользовательские запросы.

Некоторые примеры

Настройка теста:

class Photo(models.Model): tags = models.ManyToManyField('Tag') class Tag(models.Model): name = models.CharField(max_length=50) def __unicode__(self): return self.name In [2]: t1 = Tag.objects.create(name='holiday') In [3]: t2 = Tag.objects.create(name='summer') In [4]: p = Photo.objects.create() In [5]: p.tags.add(t1) In [6]: p.tags.add(t2) In [7]: p.tags.all() Out[7]: [<Tag: holiday>, <Tag: summer>] In [8]: Photo.objects.filter(tags=t1).filter(tags=t2) Out[8]: [<Photo: Photo object>]

Результирующий запрос:

In [17]: print Photo.objects.filter(tags=t1).filter(tags=t2).query SELECT "test_photo"."id" FROM "test_photo" INNER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id") INNER JOIN "test_photo_tags" T4 ON ("test_photo"."id" = T4."photo_id") WHERE ("test_photo_tags"."tag_id" = 3 AND T4."tag_id" = 4 )

Обратите внимание, что каждый filter добавляет больше JOINS к запросу.

In [29]: from django.db.models import Count In [30]: Photo.objects.filter(tags__in=[t1, t2]).annotate(num_tags=Count('tags')).filter(num_tags=2) Out[30]: [<Photo: Photo object>]

Результирующий запрос:

In [32]: print Photo.objects.filter(tags__in=[t1, t2]).annotate(num_tags=Count('tags')).filter(num_tags=2).query SELECT "test_photo"."id", COUNT("test_photo_tags"."tag_id") AS "num_tags" FROM "test_photo" LEFT OUTER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id") WHERE ("test_photo_tags"."tag_id" IN (3, 4)) GROUP BY "test_photo"."id", "test_photo"."id" HAVING COUNT("test_photo_tags"."tag_id") = 2

AND ed Q объекты не будут работать:

In [9]: from django.db.models import Q In [10]: Photo.objects.filter(Q(tags__name='holiday') & Q(tags__name='summer')) Out[10]: [] In [11]: from operator import and_ In [12]: Photo.objects.filter(reduce(and_, [Q(tags__name='holiday'), Q(tags__name='summer')])) Out[12]: []

Результирующий запрос:

In [25]: print Photo.objects.filter(Q(tags__name='holiday') & Q(tags__name='summer')).query SELECT "test_photo"."id" FROM "test_photo" INNER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id") INNER JOIN "test_tag" ON ("test_photo_tags"."tag_id" = "test_tag"."id") WHERE ("test_tag"."name" = holiday AND "test_tag"."name" = summer )

qaru.site

Лучшие 'django-filter' Вопросы - Qaru

Django-фильтр - это многозадачное приложение Django, позволяющее пользователям фильтровать queryset динамически. Для этого требуется Python 2.7+ и Django 1.8+ Используйте тег django-queryset для вопросов, связанных с методом `.filter` в QuerySets.

Если для поля, которое вы хотите фильтровать, у вас больше, чем ~ 10 значений, боковая панель фильтрации становится уродливой и сложной в использовании. Я ищу решение для замены <li> выпадающим списком (combobox) или чем-то подобным, которое ...

задан 25 марта '11 в 9:30

Есть ли фильтр-фильтр в django, который будет обрезать любые начальные или конечные пробелы из входного текста. Что-то вроде {{ var.example|trim }}

задан 28 апр. '12 в 9:35

Есть ли способ вызвать фильтр в наборе запросов, где одно из имен полей является переменной? Например, у меня есть что-то вроде: models.py class Playlist(models.Model): video = ... views.py field_name = 'video' Playlist.objects.filter(field...

задан 03 февр. '12 в 3:37

Я работаю с API, созданным из рамки Django rest, Я пытаюсь сделать фильтр для JSON Это мой serializers.py файл from rest_framework import serializers from .models import Establecimiento,Categoria,Ciudad,Zona import django_filters class Establecimi...

задан 27 янв. '14 в 9:21

У меня есть фильтр (один из стандартных и нестандартных) Можно ли просто изменить заголовок фильтра, не записывая полный новый настраиваемый фильтр? Потому что единственная настройка, которая мне нужна из фильтра, - это его название. Это должен быт...

задан 30 июня '13 в 18:45

Я использую Django 1.7.1, а я pip установил django-фильтры для своего виртуального env в /.virtualenvs/auction2/lib/python2.7/site-packages$ Он сказал, что он был успешно установлен. Итак, я разместил django-фильтры в установленных приложениях так:...

задан 28 апр. '15 в 23:21

У меня есть приложение для статьи и вы пытаетесь создать настраиваемый фильтр, у меня есть каталог с именем templatetags в приложении статьи и tag.py внутри этого каталога, вот структура каталогов. -manage.py(f) -settings.py(f) -articles(d) - templ...

задан 09 апр. '11 в 14:21

Я использую django-rest-framework с django-filter. Мне нужно получить список виджетов, где свойство date равно None, но независимо от того, какой запрос я пытался, я получаю либо пустые ответы, либо полные, нефильтрованные ответы. Вот как я определ...

задан 03 февр. '14 в 7:23

Я использую django-filter с django-rest-framework, и я пытаюсь создать экземпляр фильтра, который принимает списки номеров для фильтрации заданного запроса class MyFilter(django_filters.FilterSet): ids = django_filters.NumberFilter(name='id',...

задан 04 июня '14 в 18:31

Я хотел бы отфильтровать параметры запроса в моем REST API - посмотреть django docs на этом. Однако один параметр, который я хочу фильтровать, доступен только с помощью модели @property example models.py: class Listing(models.Model): product = ...

задан 25 июня '14 в 20:24

Я хочу отфильтровать мою модель с помощью django-filter. Он отлично работает, если я фильтрую один идентификатор, например: http://localhost:8000/accommodations?accommodationType_id=1 Но я не знаю, как я могу фильтровать несколько идентификаторов ...

задан 24 июня '15 в 17:48

Я пытаюсь заставить ModelMultipleChoiceFilter работать в течение нескольких часов и читать документацию DRF и Django Filters. Я хочу иметь возможность фильтровать набор веб-сайтов на основе тегов, которые были назначены им через ManyToManyField. Нап...

задан 06 окт. '14 в 7:56

Я работаю над api, построенным с помощью Django Rest Framework. Я определил несколько классов model, и я также создал некоторые фильтры для применения к определенным запросам, которые происходят в указанном api-endpoints. Я пытаюсь применить LIMIT ...

задан 03 нояб. '15 в 19:13

У меня есть модель Django, которая выглядит примерно так: class Response(models.Model): transcript = models.TextField(null=True) class Coding(models.Model): qid = models.CharField(max_length = 30) value = models.CharField(max_length = 2...

задан 11 мая '13 в 23:17

Можно ли упорядочить case-insensitive с помощью first_name с помощью Django-rest-framework. Вот код: import django_filter class PersonFilter(django_filters.FilterSet): class Meta: model = Person fields = ('first_name_lower',) ...

задан 06 авг. '15 в 20:44

qaru.site

django - Фильтр Django admin по умолчанию

Я решил эту проблему с поддержкой "все".

в models.py:

STATUSES_CHOICE = ( ('0', 'Active'), ('1', 'Deactive'), ('2', 'Suspended'), ) class Client(models.Model): ... status = models.IntegerField(verbose_name=_('Status'), default=0, db_index=True)

в admin.py:

class StatusAdminFilter(SimpleListFilter): title = _('Status') parameter_name = 'status' all_param_value = 'all' def lookups(self, request, model_admin): return STATUSES_CHOICE def queryset(self, request, queryset): status = self.value() try: return (queryset if status == self.all_param_value else queryset.filter(status=int(status))) except ValueError: raise Http404 def choices(self, cl): yield {'selected': self.value() == self.all_param_value, 'query_string': cl.get_query_string( {self.parameter_name: self.all_param_value}, [self.parameter_name]), 'display': _('All')} for lookup, title in self.lookup_choices: yield {'selected': self.value() == lookup, 'query_string': cl.get_query_string( {self.parameter_name: lookup}, []), 'display': title} class ClientAdmin(admin.ModelAdmin): list_filter = (StatusAdminFilter,) def changelist_view(self, request, extra_context=None): if not request.GET.has_key('status'): q = request.GET.copy() q['status'] = '0' # default value for status request.GET = q request.META['QUERY_STRING'] = request.GET.urlencode() return super(ClientAdmin, self).changelist_view( request, extra_context=extra_context)

qaru.site

python - Таблицы Django - Фильтрация столбцов

Немного поздний ответ, но в любом случае... Я также не смог найти подходящую документацию для фильтрации столбцов. Для этого есть много способов:

а. Рукой: я добавляю форму, содержащую поля, которые я хотел бы фильтровать, а затем я делаю что-то вроде этого на мой взгляд:

data = models.MyClass.all() form = forms.MyFilterForm(request.GET) if request.GET.get('field1'): data = data.filter(field1=request.GET.get('field1') ) if request.GET.get('field2'): data = data.filter(field2=request.GET.get('field2') ) ... table = tables.MyTable(data)

Это работает очень хорошо, однако оно не так сухо, потому что оно жестко закодировано в представлении.

В. Использование SingleTableView. Еще один способ - добавить SingleTableView, который содержит форму:

from django_tables2 import SingleTableView class FilteredSingleTableView(SingleTableView): def get_table_data(self): data= models.MyClass.objects.all if self.request.GET.get('field1'): data = data.filter(field1=self.request.GET.get('field1') ) if self.request.GET.get('field1'): data = data.filter(field1=self.request.GET.get('field1') ) return data def get_context_data(self, **kwargs): context = super(FilteredSingleTableView, self).get_context_data(**kwargs) context['form'] = forms.MyFilterForm(self.request.user, self.request.GET) return context

Это более DRY:)

С. Использование SingleTableView и django_filters. Это, вероятно, самый DRY-способ:) Вот как это сделать:

Сначала определите фильтр:

class MyFilter(django_filters.FilterSet): field1 = django_filters.CharFilter() field2 = django_filters.CharFilter() ...

(или вы можете добавить фильтр модели в Meta (model = MyModel)

Теперь создайте SingleTableView следующим образом

class FilteredSingleTableView(SingleTableView): def get_table_data(self): f = filters.MyFilter(self.request.GET, queryset =models.MyClass.objects.all() , request=self.request ) return f def get_context_data(self, **kwargs): context = super(FilteredSingleTableView, self).get_context_data(**kwargs) f = filters.MyFilter(self.request.GET, queryset =models.MyClass.objects.all() , request=self.request ) context['form'] = f.form return context

(возможно, существует проблема с линией f =... но я не мог заставить ее работать иначе.

Наконец, вы можете вызвать SingleTableView с вашего urls.py, как это

url(r'^$', views.FilteredSingleTableView.as_view( table_class = tables.MyTable, model=models.MyClass, template_name ='mytemplate.html', table_pagination={ "per_page":50 } )) , name='filtered_single_table_view' ),

Д. Использование универсального класса: Это еще более DRY и django-generic-class-views, как путь! Это на самом деле следующий шаг от C: просто объявите свой FilteredSingleTableView следующим образом:

class FilteredSingleTableView(django_tables2.SingleTableView): filter_class = None def get_table_data(self): self.filter = self.filter_class(self.request.GET, queryset =super(FilteredSingleTableView, self).get_table_data() ) return self.filter.qs def get_context_data(self, **kwargs): context = super(FilteredSingleTableView, self).get_context_data(**kwargs) context['filter'] = self.filter return context

Теперь FilteredSingleTableView имеет параметр для класса фильтра, поэтому вы можете передать его в urls.py среди других параметров:

url(r'^$', ships.views.FilteredSingleTableView.as_view( model=models.MyModel, table_class=tables.MyTable, template_name='mytemplate.html' , filter_class = filters.MyFilter, ) , name='myview'),

Таким образом, вы можете использовать FilteredSingleTableView без изменений для фильтрации любой из ваших моделей!

Также обратите внимание, что теперь я сохранил фильтр как переменную экземпляра и удалил повторяющийся код f=filters.MyFilter(...), который у меня был в C (get_table_data вызывается до get_context_data), если это не всегда case, то мы могли бы добавить метод экземпляра get_filter, который бы сделал трюк)!

Обновление 23/04/2016. После популярного спроса я создал простой проект Django, который использует общий класс FilteredSingleTableView для фильтрации таблицы книг. Вы можете узнать это: https://github.com/spapas/django_table_filtering

Обновление 05/07/2016. Обратите внимание, что вы должны использовать return self.filter.qs для возврата get_table_data в D (я обновил ответ с помощью это), иначе вид займет слишком много времени для больших таблиц. Более подробную информацию можно найти на https://github.com/spapas/django_table_filtering/issues/1

qaru.site