'Correct way to define list parameter in django-rest-framework and swagger

Background

I have the following view and the accompanying swagger UI is generated by django-spectacular:


class AllowedNameType(Enum):
    BRAND = "BRAND"
    ....

    @classmethod
    def list(cls):
        return list(map(lambda c: c.value, cls))

class GenerateCompanyNamesViewSet(viewsets.ViewSet):

    http_method_names = ["get"]
    
    def list(self, request: Request, *args, **kwargs) -> Response:
        """Generate suggested company names"""

        # query_params: dict = {}

        allowed_name_types: list[AllowedNameType] = query_params.get("allowed_name_types")
        suggestions: list[Suggestion] = ...

        return  Response(serializers.SuggestionSerializer(suggestions).data)

I want to achieve the following:

  1. The swagger UI should have a parameter allowed_name_types which is a list of AllowedNameType values
  2. The input should be validated as per the serializer definition
  3. Type checking should be enforced on query_params to make sure the allowed_name_types is of type list[AllowedNameType] (ideally, allowed_name_types would actually be a named parameter in (eg list(..., allowed_name_types: list[AllowedNameType])

Attempted Solution

class AllowedNameTypesParamSerializer(rest_framework_serializers.Serializer):

    allowed_name_types = rest_framework_serializers.ListField(
        child=rest_framework_serializers.ChoiceField(choices=models.AllowedNameType.list()),
        required=False,
        allow_empty=True,
    )

and added the following decorator to the list method:

@extend_schema(
        parameters=[
            OpenApiParameter(name="allowed_name_types", required=True, type=AllowedNameTypesParamSerializer),
        ],
        responses=serializers.FoodSearchAutoCompleteSerializer,
)
def list(....)

This leads to the following interface: enter image description here

Unfortunately:

  1. The swagger component expects a dictionary of {"allowed_name_types:...} instead of a list
  2. the allowed_name_types validation of list elements does not work (i.e I can put a value in the list that is not from AllowedNameType)
  3. Strangely, calling request.query_params.get('allowed_name_types') only returns the last value from the allowed_name_types.

Help?

I'm sure I have all the pieces of the jigsaw to achieve what I want, but I cannot figure out how to piece them together to give me the well documented API and typed validated behaviour that I'm after. Any help would be much appreciated :)



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source