Django rest framework поиск по полю
im trying to filter search a rest api page and want to use a method field as one of the search fields, however when I do this I get an error stating the field is not valid and it then lists the field in my model as the only valid source
how can include the safe_subnet in the search fields?
EDIT This is the code now
Do you need to use a ?search= for all of these, or can you use a custom filter that supports ?subnet=192.168/24&device=django&circut=31 style queries? The latter is preferable, in this kind of situation.
Справочник по Transform ¶
Transform - это универсальный класс для реализации преобразований поля. Ярким примером является __year , который преобразует DateField в IntegerField .
Обозначение для использования Transform в поисковом выражении: __ (например, date__year ).
Этот класс следует за API запроса , что подразумевает, что вы можете использовать ____ . Это специализированное Func () выражение , которое принимает только один аргумент. Его также можно использовать с правой стороны фильтра или непосредственно в качестве аннотации.
Логическое значение, указывающее, должно ли это преобразование применяться как к lhs , так и к rhs . Двусторонние преобразования будут применены к rhs в том же порядке, в котором они отображаются в поисковом выражении. По умолчанию установлено значение False . Для примера использования смотрите howto/custom-lookups .
Левая сторона - что трансформируется. Она должна следовать API запроса .
Имя поиска, используемое для его идентификации при разборе выражений запроса. Он не может содержать строку "__" .
Определяет класс, который выводит это преобразование. Это должен быть экземпляр Field . По умолчанию совпадает с его lhs.output_field .
API выражения запроса¶
API выражений запросов - это общий набор методов, классы которых определяют для использования в выражениях запросов для преобразования себя в выражения SQL. Прямые ссылки на поля, агрегаты и Transform являются примерами, которые следуют этому API. Говорят, что класс следует API-интерфейсу выражения запроса, когда он реализует следующие методы:
as_sql ( compiler , connection )¶
Создает фрагмент SQL для выражения. Возвращает кортеж (sql, params) , где sql - строка SQL, а params - список или кортеж параметров запроса. compiler - это объект SQLCompiler , который имеет метод compile() , который можно использовать для компиляции других выражений. connection - это соединение, используемое для выполнения запроса.
Пользовательские аргументы ключевых слов могут быть определены в этом методе, если существует вероятность, что методы или подклассы as_vendorname() должны будут предоставить данные для переопределения генерации строки SQL. Смотрите Func.as_sql() для примера использования.
as_vendorname ( compiler , connection )¶
Должен вернуть поиск с именем lookup_name . Например, возвращая self.output_field.get_lookup(lookup_name) .
Должен вернуть поиск с именем transform_name . Например, возвращая self.output_field.get_transform(transform_name) .
Определяет тип класса, возвращаемого методом get_lookup() . Это должен быть экземпляр Field .
4.1. Сериализатор
Сериализация — процесс перевода структуры данных в последовательность байтов. Она используется для передачи объектов по сети и для сохранения их в файлы (Википедия).
hotel_app/serializers.py :
Сериализаторы определяют, как именно и какие данные отобразит представление API. При запросе по REST API к экземпляру модели Hotel мы получим список следующих полей, взятых из самой модели при помощи сериализатора:
Фильтрация по URL-адресу¶
Другой стиль фильтрации может включать ограничение набора запросов на основе некоторой части URL.
Например, если ваша конфигурация URL содержит запись, подобную этой:
Затем вы можете написать представление, которое возвращает набор запросов на покупку, отфильтрованный по имени пользователя в части URL:
3.9. Административная панель
Django поставляется со встроенной панелью администратора, что позволяет создать суперпользователя с помощью одной команды. Заполните форму — появится учетная запись администратора:
Снова выполните миграции, авторизуйтесь.
Настройка интерфейса¶
Общие фильтры могут также представлять интерфейс в просматриваемом API. Для этого необходимо реализовать метод to_html() , который возвращает отрисованное HTML-представление фильтра. Этот метод должен иметь следующую сигнатуру:
to_html(self, request, queryset, view)
Метод должен возвращать отрендеренную строку HTML.
Фильтруем в django
Предвосхищая вопросы, касательно кода из спойлера — время исполнения скрипта является обоснованной метрикой в том и только том случае, если с queryset были проведены какие-либо операции. Поэтому я вывожу длину получившегося ответа.
A QuerySet is iterable, and it executes its database query the first time you iterate over it. For example, this will print the headline of all entries in the database:
Так что в итоге?
Если у вас есть большой объём данных — нужно прописывать нормальные индексы и использовать полнотекстовый поиск (разумеется, только в том случае, когда соответствует вашим целям) с радостью и счастьем, потому что он решает довольно широкий круг проблем. Но вот всегда ли в нём есть необходимость — уже решать вам. Я усвоил для себя, что в некоторых случаях (когда не стоит задачи именно полнотекстового поиска, а есть поиск по подстроке, который реализуется с помощью contains/icontains) лучше вовсе не использовать полнотекстовый поиск, потому что индексы в определённый момент начинают кушать всё больше и больше памяти вашего сервера, что, скорее всего, негативно скажется на работе вашего сервера.
В целом, моё понимание некоторых внутренних механизмов работы django благодаря этому исследованию устаканилось. И пришло, наконец, осознание разницы между поиском по подстроке и полнотекстовым поиском. Разнице в их реализации через Django ORM.
Корневой QuerySet, предоставляемый менеджером, описывает все объекты в таблице базы данных. Обычно, однако, вам нужно выбрать только подмножество полного набора объектов.
‒ Django documentation
По умолчанию общие представления списков в REST framework возвращают весь набор запросов для менеджера модели. Часто вы хотите, чтобы ваш API ограничивал элементы, возвращаемые набором запросов.
Самый простой способ фильтровать набор запросов любого представления, которое является подклассом GenericAPIView , - это переопределить метод .get_queryset() .
Переопределение этого метода позволяет вам настроить набор запросов, возвращаемый представлением, различными способами.
Фильтрация и поиск объектов¶
Обратите внимание, что если бэкэнд фильтра настроен для представления, то помимо того, что он используется для фильтрации представлений списка, он также будет использоваться для фильтрации наборов запросов, используемых для возврата одного объекта.
Например, учитывая предыдущий пример и продукт с идентификатором 4675 , следующий URL либо вернет соответствующий объект, либо выдаст ответ 404, в зависимости от того, были ли выполнены условия фильтрации для данного экземпляра продукта:
Django REST framework полный фильтр поиска слов¶
djangorestframework-word-filter разработан как альтернатива filters.SearchFilter , который будет искать полное слово в тексте, или точное совпадение.
Настройка бэкендов фильтров¶
Бэкенды фильтров по умолчанию могут быть установлены глобально, с помощью параметра DEFAULT_FILTER_BACKENDS . Например.
Вы также можете установить бэкенды фильтров на основе каждого представления или каждого набора представлений, используя представления на основе классов GenericAPIView .
3.12. Добавление приложения в админ-панель
Во встроенное приложение административной панели можно добавить созданную ранее пользовательскую модель.
hotel_app/admin.py :
Теперь мы завершили ту общую часть разработки веб-приложения, которая относится к фреймворку Django. Настало время приступить к проектированию REST API.
Структура директорий проекта:
Добавим в проект файлы urls.py и serializers.py . Вот новый список файлов.
3.10. Создание модели
Django ORM абстрагирует базу данных, позволяя легко запрашивать данные и манипулировать ими через объектно-ориентированное отображение, называемое моделью. Django ORM заставляет писать код согласно паттерну MVC (Model View Controller), который станет интуитивно понятным для вас после прохождения кривой обучения.
hotel_app/models.py :
Мы создали модель, хранящую имя студента и его оценки. Метод __str__ определяет имя объекта, отображаемое в браузере. Если пропустить определение данного метода, то вы увидите в панели администратора объект под названием .
Указание того, какие поля могут быть заказаны против¶
Рекомендуется явно указать, какие поля API должен разрешить в фильтре упорядочивания. Вы можете сделать это, установив атрибут ordering_fields на представлении, как показано ниже:
Это помогает предотвратить непредвиденную утечку данных, например, разрешение пользователям делать заказы по хэш-полю пароля или других конфиденциальных данных.
Если вы не укажете атрибут ordering_fields на представлении, класс фильтра по умолчанию позволит пользователю фильтровать по любым читаемым полям на сериализаторе, указанном атрибутом serializer_class .
Если вы уверены, что кверисет, используемый представлением, не содержит конфиденциальных данных, вы также можете явно указать, что представление должно разрешить упорядочивание по любому полю модели или агрегату кверисета, используя специальное значение '__all__' .
Пагинация и схемы¶
Вы также можете сделать элементы управления фильтром доступными для автогенерации схемы, которую обеспечивает REST framework, реализовав метод get_schema_fields() . Этот метод должен иметь следующую сигнатуру:
Метод должен возвращать список экземпляров coreapi.Field .
Следующие пакеты сторонних производителей предоставляют дополнительные реализации фильтров.
Начало работы
Первая проблема, которая передо мной встала — поиск мокапа БД, чтобы не придумать каких-нибудь непонятных штук самому и я отправился гуглить и читать вики постгреса. В итоге остановился на их демо базе о полётах по России.
Хорошо, база найдена. Теперь нужно определиться в том, какие способы фильтрации будут использоваться для сравнения. Первое, что я бы хотел использовать, разумеется, стандартный метод search из django.contrib.postgres.search. Второе — contains (ищет слово в строке) и icontains (предоставляет данные, игнорируя акценты, например: по запросу "Helen" будет результат: , , ), которые предоставляет сам django. Все эти способы фильтрации я так же хочу сравнить со встроенным поиском внутри postgresql. Искать я решил по таблице tickets в версии small она содержит 366733 записей. Поиск будет происходить по полю passenger_name, где, как нетрудно догадаться, содержится имя пассажира. Написано оно транслитом.
3.6. Создание приложения
Приложения в Django — это независимые многократно используемые компоненты. Создадим приложение hotel_app .
3.3. Начало проекта
Django URL Filter¶
django-url-filter предоставляет безопасный способ фильтрации данных через удобные для человека URL. Он работает очень похоже на сериализаторы и поля DRF в том смысле, что они могут быть вложенными, за исключением того, что они называются filtersets и filters. Это обеспечивает простой способ фильтрации связанных данных. Также эта библиотека является универсальной, поэтому ее можно использовать для фильтрации других источников данных, а не только Django QuerySet s.
ЗаказФильтр¶
Класс OrderingFilter поддерживает простое упорядочивание результатов, управляемое параметрами запроса.
По умолчанию параметр запроса называется 'ordering' , но это можно отменить с помощью параметра ORDERING_PARAM .
Например, чтобы упорядочить пользователей по имени пользователя:
Клиент также может указать обратный порядок, добавив к имени поля префикс „-„, как показано ниже:
Также можно указать несколько порядков:
3.5. Запуск сервера
3.4. Изменение директории
4.2. Представления
Файл представления определяет то, как сериализованные объекты отображаются пользователю.
3.1. Создание виртуальной среды
Справочник по Lookup ¶
Lookup - это универсальный класс для реализации поиска. Поиск - это выражение запроса с левой стороны lhs ; правой стороны rhs ; и lookup_name , которое используется для получения логического сравнения между lhs и rhs , такого как lhs in rhs или lhs > rhs .
Основной нотацией для использования поиска в выражении является __= . Поиск можно также использовать непосредственно в фильтрах QuerySet :
Левая часть - то, что ищется. Объект обычно следует за Query Expression API . Это может быть и простое значение.
Правая часть - с чем сравнивается lhs . Это может быть простое значение или что-то, что компилируется в SQL, обычно это объект F() или QuerySet .
Имя этого поиска, используется для его идентификации при разборе выражений запроса. Он не может содержать строку "__" .
Ведет себя так же, как process_lhs() , для правой части.
Добавлена поддержка использования поиска в аннотациях QuerySet , агрегациях и непосредственно в фильтрах.
Термин REST API расшифровывается как Representational State Transfer Application Programming Interface. Следовательно, RESTful API — это программный интерфейс приложения, соответствующий ограничениям архитектурного стиля REST.
REST — не протокол и не стандарт. Это, как уже было сказано, архитектурное ограничение. Чтобы API считался RESTful, он должен соответствовать следующим критериям.
Благодаря вышеперечисленным архитектурным правилам REST API масштабируемый, переносимый и гибкий.
Django — масштабируемый полнофункциональный веб-фреймворк, написанный на Python. Django берет на себя все хлопоты, зачастую связанные с веб-разработкой, такие как безопасность и доступ к базам данных.
Существует множество библиотек для Django, расширяющих его функционал. Одна из них, о которой мы поговорим сегодня, — это Django REST Framework или DRF, которая позволяет сериализовать данные из Django ORM через REST API.
Сериализация — это преобразование таблиц из базы данных в формат JSON.
Руководство написано для новичков, прошлый опыт работы с фреймворком Django не предполагается, так как вы многому научитесь прямо сейчас. Кроме того, в статье не будет обширного описания технических нюансов каждой операции. Рассматривайте руководство в качестве упражнения.
Давайте создадим сайт бронирования отелей! Исходный код и справка доступны на GitHub.
Прежде чем приступить непосредственно к работе с REST API, сделаем краткий экскурс в Django.
Full text search (через django.contrib.postgres)
Поскольку индексов никаких создано не было, full text search довольно сильно и вполне ощутимо проигрывает прошлым вариантам. Время исполнения запроса в постгресе колеблется около 1300 мс, а запрос к серверу занимает от 1000 до 1700 мс. При этом, фильтрация через ORM — укладывается в промежуток от 1000 до 1450 мс.
4.3. URL: ссылки на ресурсы
hotel_app/urls.py :
hotel_reservation/urls.py :
Перейдя по данной ссылке, вы получите доступ ко всем ранее определенным “разделам” REST API проекта:
Фильтрация по текущему пользователю¶
Вы можете захотеть отфильтровать набор запросов, чтобы гарантировать, что будут возвращены только результаты, относящиеся к текущему аутентифицированному пользователю, сделавшему запрос.
Пример¶
Например, вам может понадобиться ограничить доступ пользователей только к созданным ими объектам.
Мы могли бы добиться такого же поведения, переопределив get_queryset() в представлениях, но использование бэкенда фильтра позволяет вам легче добавить это ограничение к нескольким представлениям или применить его ко всему API.
Icontains
Icontains работает несколько по-другому (он приводит всё к одному виду, чтобы сравнение было более близким). Код для вьюшки использовался почти аналогичный, только вместо contains — icontains. Вот и вся разница.
По итогу, отклонение в данном случае уже меньше, поскольку и сам постгрес начал тратить намного большее времени на исполнение запроса (порядка 300 мс), а исполнение такого запроса к серверу займёт у клиента от 200 до 1500 мс. Фильтрация через ORM — от до 200 до 700 мс.
3.2. Установка зависимостей
3.8. Миграции
Теперь нужно выполнить Django-миграции — это способ Django распространять в схему базы данных все изменения, вносимые в модели, такие как добавление поля, удаление модели. Выполняйте эту команду каждый раз, когда модель или база данных сколько-нибудь меняются:
Full text search (через rest_framework.filters, точнее — SearchFilter)
Если не использвоать именно FTS, то результаты получаются сравнимыми с FTS внутри постгре, но хуже, чем contains и icontains. От 200 до 1710 мс.
А с использованием FTS эффективность повышается, отклонение сводится к минимальному. В среднем, это займёт от 800 до 1120 мс.
Пакет фильтров фреймворка Django REST¶
Класс django-rest-framework-filters package работает вместе с классом DjangoFilterBackend и позволяет легко создавать фильтры по отношениям или создавать несколько типов поиска фильтра для определенного поля.
drf-url-filters¶
drf-url-filter - это простое Django приложение для применения фильтров к drf ModelViewSet „s Queryset чистым, простым и настраиваемым способом. Оно также поддерживает валидацию входящих параметров запроса и их значений. Для проверки входящих параметров запроса используется красивый пакет python Voluptuous . Самое лучшее в voluptuous то, что вы можете определить свои собственные валидации в соответствии с требованиями к параметрам запроса.
Этот документ содержит ссылки на API для поиска, API Django для построения WHERE запроса к базе данных. Чтобы узнать, как использовать поиски, смотрите Создание запросов ; чтобы узнать, как создавать новые поиски, смотрите Как писать пользовательские поисковые запросы .
API поиска имеет два компонента: RegisterLookupMixin , который регистрирует поиск, и API выражения запроса , набор методов, которые класс должен реализовать, чтобы быть зарегистрирированным как поиск.
У Django есть два базовых класса, которые следуют API-интерфейсу выражения запроса и откуда берутся все встроенные поиски Django:
-
: для поиска поля (например, exact из field_name__exact ) : для преобразования поля
Выражение поиска состоит из трех частей:
- Часть полей (например, Book.objects.filter(author__best_friends__first_name. );
- Преобразуемая часть (может быть опущена) (например, __lower__first3chars__reversed );
- Поиск (например, __icontains ), который, если не указан, по умолчанию равен __exact .
DjangoFilterBackend¶
Библиотека ** ``django-filter :doc:` ` включает класс DjangoFilterBackend , который поддерживает высоконастраиваемую фильтрацию полей для REST-фреймворка.
Чтобы использовать DjangoFilterBackend , сначала установите django-filter .
Затем добавьте 'django_filters' к INSTALLED_APPS в Django:
Теперь вам следует либо добавить бэкенд фильтра в настройки:
Или добавьте бэкэнд фильтра к отдельному представлению или набору представлений.
Если вам нужна простая фильтрация на основе равенства, вы можете установить атрибут filterset_fields на представлении или наборе представлений, перечисляющий набор полей, по которым вы хотите фильтровать.
Это автоматически создаст класс FilterSet для заданных полей, и позволит вам делать такие запросы, как:
Для более сложных требований к фильтрации вы можете указать FilterSet класс, который должен использоваться представлением. Вы можете прочитать больше о FilterSet s в django-filter documentation . Также рекомендуется прочитать раздел DRF integration .
Использование фильтров через модуль django-filter
Результаты почти совпали со стандартными contains и icontains, поэтому смысла детально это рассматривать не вижу. Да и в целом, модуль django-filter не показал какого-то ощутимого преимущества перед стандартными средствами фильтрации Django ORM.
Указание порядка по умолчанию¶
Если в представлении установлен атрибут ordering , он будет использоваться в качестве упорядочивания по умолчанию.
Обычно вы контролируете это, устанавливая order_by в начальном наборе запросов, но использование параметра ordering в представлении позволяет вам указать упорядочивание таким образом, что оно может быть автоматически передано в качестве контекста в шаблон рендеринга. Это позволяет автоматически отображать заголовки столбцов по-разному, если они используются для упорядочивания результатов.
Атрибут ordering может быть либо строкой, либо списком/кортежем строк.
Вы также можете предоставить свой собственный общий бэкэнд фильтрации или написать устанавливаемое приложение для использования другими разработчиками.
Для этого переопределите BaseFilterBackend , и переопределите метод .filter_queryset(self, request, queryset, view) . Метод должен вернуть новый, отфильтрованный набор запросов.
Помимо того, что клиенты могут выполнять поиск и фильтрацию, общие бэкенды фильтров могут быть полезны для ограничения того, какие объекты должны быть видны для каждого конкретного запроса или пользователя.
Переопределение начального набора queryset¶
Обратите внимание, что вы можете использовать и переопределенный .get_queryset() , и общую фильтрацию вместе, и все будет работать, как ожидалось. Например, если Product имеет отношения «многие-ко-многим» с User , названными purchase , вы можете написать представление следующим образом:
Фильтрация по параметрам запроса¶
Последним примером фильтрации начального набора запросов может быть определение начального набора запросов на основе параметров запроса в url.
Помимо возможности переопределения набора запросов по умолчанию, REST framework также включает поддержку общих бэкендов фильтрации, которые позволяют легко создавать сложные поиски и фильтры.
Общие фильтры также могут быть представлены в виде элементов управления HTML в просматриваемом API и API администратора.
3.11. Не забывайте о миграциях!
Теперь, когда изменения уже внесены в модель, настало время выполнить миграции.
3 Answers 3
You need to annotate your queryset with the safe_subnet attribute so it becomes searchable.
Then in your serializer you can use the following.
If the error is caused by the filter then it's possibly a result of this DRF issue and you should be able to solve by upgrading. Otherwise, if the serializer is used outside SubnetDetailsSet and the queryset isn't annotated then you would also get this error. You could change to return getattr(obj, 'safe_subnet', None) if you don't want to annotate for some reason.
@AlexW does the annotation work when you use it in the shell? You need to look at the traceback and see what's causing the error. Likely SearchFilter doesn't call the view's .get_queryset() method before filtering so you need to figure out how to do that.
the annotation works through shell yes, I have no idea how to edit the search filter to include that, would you happen to know how to do this? Thanks
Previous answer with annotate is a really good start:
Now in rest_filters.py
Please note: I'm annotating safe_subnet within the filer, depending on how much you use this, you might want to set this up in your model's manager!
I'm getting Error: safe_subnet = django_filters.IntegerField( AttributeError: module 'django_filters' has no attribute 'IntegerField'
I still see the same AttributeError: module 'django_filters.rest_framework' has no attribute 'IntegerField'
ok its gone back to the original error now for some reason "Cannot resolve keyword 'safe_subnet' into field"
Going in a completely different direction from the other (excellent) answers. Since you want to be able to filter frequently on the safe_subnet field, why not just let it be an actual database field in your model? You could calculate and populate/update the value during one of your save methods and then just let django-filters do it's thing. This also has the advantage of allowing the filtering to be done directly through SQL which would theoretically provide better performance.
Началось всё с того, что мне предложили в рамках предмета "Основы веб-программирования" поучаствовать в проекте, вместо проделывания лабораторных работ и курсовой, поскольку я заявил о том, что хотел быть делать нечто отдалённое от общего курса (и так уже достаточно знаний было по связке DRF + Vue, хотелось чего-то нового). И вот в одном из своих PR на github я решил использовать полнотекстовый поиск (задание намекало на это) для фильтрации контента, что заставило меня обратиться к документации Django в поисках того, каким же образом лучше это дело реализовать. Думаю, вы знаете большую часть из тех методов, что были там предложены (contains, icontains, trigram_similar). Все они подходят для каких-то конкретных задач, но не слишком хороши в, именно, полнотекстовом поиске. Пролистав чуть ниже, я наткнулся на раздел, в котором говорилось о взаимодействии Django и Pgsql для реализации document-based поиска, что меня привлекло, поскольку в постгре встроен инструмент для реализации этого самого [полнотекстового] поиска. И я решил, что скорее всего, django просто предоставляет API к этому поиску, исходя из чего такое решение должно работать и точнее и быстрее, чем любые другие варианты. Преподаватель мне не слишком поверил, мы с ним поспорили, и он предложил провести исследование на эту тему. И вот я здесь.
3.7. Список приложений в проекте
Чтобы подключить к проекту hotel_reservation приложения hotel_app и rest_framework , необходимо отредактировать файл results/settings.py , указав эти приложения в списке INSTALLED_APPS :
API регистрации¶
Django использует RegisterLookupMixin , чтобы дать классу интерфейс для регистрации поисков на себя. Два выдающихся примера Field , базовый класс всех полей модели и Transform , базовый класс всех преобразований Django.
class lookups. RegisterLookupMixin ¶
Миксин, который реализует API поиска в классе.
classmethod register_lookup ( lookup , lookup_name = None )¶
Регистрирует новый поиск в классе. Например, DateField.register_lookup(YearExact) зарегистрирует YearExact поиск в DateField . Он отменяет поиск, который уже существует с тем же именем. lookup_name будет использоваться для этого поиска, если он указан, в противном случае будет использоваться lookup.lookup_name .
Чтобы класс был поиском, он должен следовать API выражения запроса . Lookup и Transform естественно следуют этому API.
SearchFilter¶
Класс SearchFilter поддерживает простой поиск на основе одного параметра запроса и основан на Django admin’s search functionality.
При использовании просматриваемый API будет включать элемент управления SearchFilter :
Класс SearchFilter будет применяться только в том случае, если у представления установлен атрибут search_fields . Атрибут search_fields должен представлять собой список имен полей текстового типа в модели, например CharField или TextField .
Это позволит клиенту фильтровать элементы в списке, делая такие запросы, как:
Вы также можете выполнить связанный поиск по полю ForeignKey или ManyToManyField с помощью нотации двойного андерскора API поиска:
Для полей JSONField и HStoreField вы можете фильтровать на основе вложенных значений внутри структуры данных, используя ту же нотацию с двойным индексированием:
По умолчанию при поиске используются частичные совпадения без учета регистра. Параметр поиска может содержать несколько условий поиска, которые должны быть разделены пробелами и/или запятыми. Если используется несколько условий поиска, то объекты будут возвращены в списке только в том случае, если совпадут все указанные условия.
Поведение поиска может быть ограничено путем добавления различных символов к search_fields .
„^“ Начинается с поиска.
„@“ Полнотекстовый поиск. (В настоящее время поддерживается только Django’s PostgreSQL backend ).
По умолчанию параметр поиска называется 'search' , но это может быть отменено настройкой SEARCH_PARAM .
Чтобы динамически изменять поля поиска в зависимости от содержимого запроса, можно создать подкласс SearchFilter и переопределить функцию get_search_fields() . Например, следующий подкласс будет искать по title , только если в запросе присутствует параметр запроса title_only :
Более подробную информацию см. в разделе Django documentation .
Выбор метрик
Изначально я подумал, что считать время фильтрации в питоне получится, используя таймер для получения времени исполнения скрипта, и дополнительной метрикой должно было стать время исполнения запроса через curl, поскольку это показывает приблизительное время, за которое отфильтрованные данные дойдут до конечного пользователя. Кроме этого, следует сравнивать это время с эталонным (прямым исполнением соответствующих запросов в БД).
Дать django возможность работать с уже существующей БД
Вторая проблема — разрешить django только чтение данных из нашей демонстрационной БД. Покопавшись ещё в документации django я нашёл каким же образом, можно составить модельки по существующей БД, чтобы не перепечатывать ручками всё:
Contains
Начнём с contains, по сути, он работает как WHERE LIKE.
Для того, чтобы получить результат из curl я выполнял запрос следующим образом (считается в секундах):
Свёл всё в таблице, на соответствующем листе.
Но если резюмировать — отклонение от скорости фильтрации внутри самого постгреса достаточно большое, и по факту исполнение такого запроса к серверу займёт от 140 до 1400 мс. Не претендую на истину, но работает всё приблизительно так. А время самой фильтрации через ORM займёт от 73 до 600 мс, в то время как такая же фильтрация внутри постгреса выполняется за промежуток от 55 до 100 мс.
Читайте также: