Django: Создание вариантов для фильтра на основе различных значений модели

Задача: Я хочу, чтобы на странице отображалась ModelChoiceFilter, где опции/варианты для выбора пользователем являются различными значениями поля в модели.

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


Я использую django-filters и у меня успешно работает MultipleChoiceFilter, где выбор работает при жестком кодировании (либо в models.py, либо в классе FilterForm:

).
class cityFilter(django_filters.FilterSet):

    continent = MultipleChoiceFilter(
        choices=cityModel.continent_choices,
        widget=forms.CheckboxSelectMultiple,
        label='Continent')

    class Meta:
        model = cityModel
        fields = ['city', 'country', 'continent']

Можно также установить выбор непосредственно в классе FilterSet следующим образом:

country = MultipleChoiceFilter(
    choices=(('GB','United Kingdom'),('FR','France')),
    widget=forms.CheckboxSelectMultiple,
    label='Country'
)

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


Я мог бы сделать что-то вроде этого, чтобы получить все отдельные страны в модели:

country_choices = cityModel.objects.values('country').distinct()

Но я не уверен, где это должно быть размещено в приложении, чтобы получить запрос при загрузке страницы, а затем нужно взять каждое значение в наборе запросов и итерировать, чтобы превратить его в кортеж "выбор".

Есть ли лучший шаблон/подход?

Если вам нужен динамический выбор и данные о выборе из Model, вы можете попробовать использовать queryset в ModelMultipleChoiceFilter следующим образом:

continent = ModelMultipleChoiceFilter(
            queryset=cityModel.objects.values('country').distinct(),
            widget=forms.CheckboxSelectMultiple,
            label='Continent')
Вернуться на верх