carltongibson / django-filter

A generic system for filtering Django QuerySets based on user selections
https://django-filter.readthedocs.io/en/main/
Other
4.39k stars 758 forks source link

Support group mappings as dictionares introduced in Django 5.0 #1667

Open saevarom opened 3 weeks ago

saevarom commented 3 weeks ago

Problem Django 5.0 introduced a new way to define option groups (https://docs.djangoproject.com/en/5.0/releases/5.0/#more-options-for-declaring-field-choices). django-filters already supports option groups via the older method using a list of 2-tuples, but fails to account for the dictionary option. Example using django-filters version 24.2:

>>> import django_filters
>>> django_filters.VERSION
(24, 2)
>>> class MyDateRangeFilter(DateRangeFilter):
...     choices=[ # choices defined using a list of 2-tuples
...         ("Martial Arts", [("judo", "Judo"), ("karate", "Karate")]),
...         ("Racket", [("badminton", "Badminton"), ("tennis", "Tennis")]),
...         ("unknown", "Unknown"),
...     ]
...     filters = {
...         "judo": "Judo",
...         "karate": "Karate",
...         "badminton": "Badminton",
...         "tennis": "Tennis",
...         "unknown": "Unknown",
...     }
...
>>> MyDateRangeFilter()
<MyDateRangeFilter object at 0xffff77bb0eb0>
>>> class MyDateRangeFilter(DateRangeFilter):
...     choices = {  # Using a mapping instead of a list of 2-tuples.
...         "Martial Arts": {"judo": "Judo", "karate": "Karate"},
...         "Racket": {"badminton": "Badminton", "tennis": "Tennis"},
...         "unknown": "Unknown",
...     }
...     filters = {
...         "judo": "Judo",
...         "karate": "Karate",
...         "badminton": "Badminton",
...         "tennis": "Tennis",
...         "unknown": "Unknown",
...     }
...
>>> MyDateRangeFilter()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/local/lib/python3.8/site-packages/django_filters/filters.py", line 491, in __init__
    assert not unique, (
AssertionError: Keys must be present in both 'choices' and 'filters'. Missing keys: 'M, R, badminton, judo, karate, tennis, u, unknown'

Solution Account for the dictionary when accepting choices and flatten it down in the same way as the list of 2-tuples.

carltongibson commented 3 weeks ago

Fancy making a PR @saevarom ?

saevarom commented 3 weeks ago

I will probably do that @carltongibson , I'm currently at the Wagtail sprint in Arnhem, Netherlands, where we ran into this issue :)

carltongibson commented 3 weeks ago

Great. Have fun! 🥳