Django-filter: Разрешить переопределить получение набора запросов в FilterSet

Созданный на 21 июн. 2017  ·  4Комментарии  ·  Источник: carltongibson/django-filter

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

Вот мой вариант использования.
Я фильтрую набор запросов по отношению M2M (как в queryset.filter(items__field="foo") ). Однако я хочу, чтобы предварительно загруженные элементы также фильтровались по этому полю.

Другими словами, мой фильтр выглядит так:

# In my filterset
def filter_items_by_field(self, queryset, name, value):
        queryset = queryset.all().filter(
            items__field=value,
        )
        prefetched_items = Prefetch(
            'items',
            Item.objects..filter(
                field=value,
            ),
        )
        return queryset.prefetch_related(prefetched_items)

# In my vieset
def get_queryset(self):
        queryset = super().get_queryset()
        # This should be applied everytime
        prefetched_items = Prefetch(
            'items',
            Item.objects..filter(
                another_field=some_value,
            ),
        )
        return queryset.prefetch_related(prefetched_items)

Такой единственный фильтр работает должным образом. Однако у меня может быть несколько фильтров filter_items_by_* + мне нужно применить ту же фильтрацию для набора запросов из предварительной выборки для всех фильтров. И несколько фильтров не проблема, потому что в моем случае они исключают друг друга. Но фильтр + универсальный вызовет исключение.

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

У меня есть временное решение этой проблемы: все filter_items_by_* выполняют обязательную фильтрацию при предварительной выборке.
И в filter_queryset (после применения фильтрации), если items не предварительно выбираются (что плохо, поскольку я проверяю атрибуты, защищенные набором запросов), я применяю предварительную выборку с обязательной фильтрацией. Но должен быть лучший способ справиться с подобными ситуациями.

Надеюсь, мой пример достаточно ясен.

Самый полезный комментарий

Привет @ Alexx-G. Выпуск 2.0 все еще остается выходом, но в API будут внесены некоторые изменения, специально посвященные этому вопросу. Суммируя,

  • Вы захотите переопределить метод .filter_queryset() . Атрибут .qs основном отвечает за вызов .filter_queryset() и кеширование его результата.
  • Вы можете получить значения фильтра для предварительной выборки из self.form.cleaned_data .

Все 4 Комментарий

Привет @ Alexx-G. Я думаю, что это возможно при некоторой координации между набором фильтров и соответствующими классами фильтров. По сути, фильтр добавит экземпляр Prefetch к своему набору фильтров parent . FilterSet.qs тогда просто вызовет prefetch_related когда это необходимо.

Тем не менее, каков вариант использования этого? Я бы сказал, что есть более подходящие места для обработки предварительной выборки.

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

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

Тем не менее, каков вариант использования этого? Я бы сказал, что есть более подходящие места для обработки предварительной выборки.

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

Другими словами, если бы было описание публичного контракта свойства qs или задокументированный хук для него, это улучшило бы настройку набора фильтров.

Привет @ Alexx-G. Выпуск 2.0 все еще остается выходом, но в API будут внесены некоторые изменения, специально посвященные этому вопросу. Суммируя,

  • Вы захотите переопределить метод .filter_queryset() . Атрибут .qs основном отвечает за вызов .filter_queryset() и кеширование его результата.
  • Вы можете получить значения фильтра для предварительной выборки из self.form.cleaned_data .

Большое спасибо за ваши усилия!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

GuillaumeCisco picture GuillaumeCisco  ·  3Комментарии

gsvr picture gsvr  ·  3Комментарии

xtrinch picture xtrinch  ·  4Комментарии

edmorley picture edmorley  ·  3Комментарии

chromakey picture chromakey  ·  5Комментарии