diff --git a/drf_spectacular/contrib/django_filters.py b/drf_spectacular/contrib/django_filters.py index 662d712a..51f57905 100644 --- a/drf_spectacular/contrib/django_filters.py +++ b/drf_spectacular/contrib/django_filters.py @@ -259,6 +259,8 @@ def _get_field_description(self, filter_field, description): # remove auto-generated enum list, since choices come from a callable if '\n\n*' in (description or ''): description, _, _ = description.partition('\n\n*') + elif (description or '').startswith('* `'): + description = '' return description choice_description = '' @@ -268,14 +270,18 @@ def _get_field_description(self, filter_field, description): if not choices: return description - if description: - # replace or append model choice description - if '\n\n*' in description: - description, _, _ = description.partition('\n\n*') + if not description: + return choice_description + + if '\n\n*' in description: + description, _, _ = description.partition('\n\n*') return description + '\n\n' + choice_description - else: + + if description.startswith('* `'): return choice_description + return description + '\n\n' + choice_description + @classmethod def _is_gis(cls, field): if not getattr(cls, '_has_gis', True): diff --git a/tests/contrib/test_django_filters.py b/tests/contrib/test_django_filters.py index bebf5808..8d661db2 100644 --- a/tests/contrib/test_django_filters.py +++ b/tests/contrib/test_django_filters.py @@ -377,3 +377,36 @@ def list(self, request, *args, **kwargs): assert schema['paths']['/x/']['get']['parameters'] == expected schema = generate_schema('/x', XViewset) assert schema['paths']['/x/']['get']['parameters'] == expected + + +def test_filterset_enum_description_duplication(): + class ThingType(models.TextChoices): + ONE = "one", "One" + TWO = "two", "Two" + THREE = "three", "Three" + + class Thing(models.Model): + type = models.CharField(max_length=64, choices=ThingType.choices) + + class ThingSerializer(serializers.ModelSerializer): + class Meta: + model = Thing + fields = ("type",) + + class ThingFilterSet(FilterSet): + class Meta: + model = Thing + fields = ("type",) + + type = ChoiceFilter(choices=ThingType.choices) + + class XViewSet(viewsets.ModelViewSet): + queryset = Thing.objects.all() + serializer_class = ThingSerializer + filter_backends = [DjangoFilterBackend] + filterset_class = ThingFilterSet + + schema = generate_schema('/x', XViewSet) + assert schema['paths']['/x/']['get']['parameters'][0]['description'] == ( + '* `one` - One\n* `two` - Two\n* `three` - Three' + )