Django-filter: Фильтрация по атрибуту модели внешнего ключа

Созданный на 9 янв. 2019  ·  4Комментарии  ·  Источник: carltongibson/django-filter

Всем привет!

Я работал над проблемой на работе и задавался вопросом, каков самый идиоматический способ ее решения. У нас есть несколько полей фильтра ModelMultipleChoiceFilter для внешних ключей модели. Я пытаюсь понять, как выполнить фильтрацию по уникальному атрибуту внешних ключей при использовании виджета CheckboxSelectMultiple , не раскрывая первичные ключи в URL-адресах.

Вот пример, который (более или менее) показывает, как я его настроил прямо сейчас.

# app/models.py
from django.db import models

class Foo(models.Model):
    prop = models.CharField(max_length=55, unique=True)

    def __str__(self):
        return self.name


class Bar(models.Model):
    foo = models.ForeignKey(Foo, related_name="bars")
# app/filters.py
import django_filters
from app.models import Bar, Foo

class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

Это прекрасно работает в представлении. Фильтры работают и фильтруют правильно с правильными виджетами. Однако в URL-адресе есть первичный ключ, поэтому в этом примере /?foo=1 , тогда как я хочу, чтобы он читал /?foo=<prop value> , чтобы предотвратить раскрытие моего pk, а также сделать URL-адреса более читабельными.

Я пробовал изменять такие поля, потому что в другом месте в Django это работает:

# app/filters.py
...snip...
    class Meta:
        model = bar
        fields = ['foo__prop']

Это заставляет URL-адрес отвечать на /?foo=<prop value> по желанию, но теперь он не использует CheckboxSelectMultiple для формы. Я также попытался превратить атрибут в foo__prop , но рендеринг формы по-прежнему был некорректным.

У меня есть ощущение, что то, что я пытаюсь сделать, поддерживается, учитывая, что он почти работает, но я не могу понять, как это получить. Если это выходит за рамки текущей поддерживаемой области, я могу написать свою собственную форму, чтобы справиться с этим. Большое спасибо за любую помощь и за отличный проект!

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

Привет, спасибо, что нашли время ответить!

Ты поставил меня на правильный путь! Вчера у меня была возможность реализовать это, и использование аргумента field_name сработало!

Для тех, кто в будущем может прочитать этот выпуск, вот пример того, как получился код:

# app/filters.py
...snip
class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        field_name="foo__prop", # This lets us keep the url as "/?foo=<value>
        to_field_name="prop",
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

Вы можете найти ссылку на это в документации, упомянутой в ветке @carltongibson . В частности, см. Раздел о фильтрах ModelMultipleChoice.

В любом случае, большое спасибо за то, что нашли время, чтобы помочь мне!

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

Привет. Хорошая проблема. Строго говоря, вопрос использования, но так хорошо сформулирован, что читать одно удовольствие.

Вы смотрели на аргумент field_name для фильтров?
https://django-filter.readthedocs.io/en/master/ref/filters.html

Это позволит вам использовать foo_prop в качестве цели для вашего фильтра foo.

Я предполагаю, что это просто сработает ... может быть, вам нужно будет установить выбор в виджете или что-то в этом роде (но это нужно обработать ...)

Привет, спасибо, что нашли время ответить!

Ты поставил меня на правильный путь! Вчера у меня была возможность реализовать это, и использование аргумента field_name сработало!

Для тех, кто в будущем может прочитать этот выпуск, вот пример того, как получился код:

# app/filters.py
...snip
class BarFilter(django_filters.FilterSet):
    foo = django_filters.ModelMultipleChoiceFilter(
        queryset=Foo.objects.all(),
        field_name="foo__prop", # This lets us keep the url as "/?foo=<value>
        to_field_name="prop",
        widget=CheckboxSelectMultiple(),
        label="Foo",
        label_suffix="",
    )

    class Meta:
        model = bar
        fields = ['foo']

Вы можете найти ссылку на это в документации, упомянутой в ветке @carltongibson . В частности, см. Раздел о фильтрах ModelMultipleChoice.

В любом случае, большое спасибо за то, что нашли время, чтобы помочь мне!

Супер. Рад, что ты это решил. Отличная работа!

Отличная работа ! Спасибо !

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