tfranzel / drf-spectacular

Sane and flexible OpenAPI 3 schema generation for Django REST framework.
https://drf-spectacular.readthedocs.io
BSD 3-Clause "New" or "Revised" License
2.38k stars 264 forks source link

Any way to extend the responses schema rather than overwriting it? #1257

Open diego351 opened 4 months ago

diego351 commented 4 months ago

@tfranzel

When it's like this (no responses kwarg passed) the default behavior for http 200 works fine,

@extend_schema_view(
    get=extend_schema(
        operation_id='Kanban endpoint',  # TODO:
        description="Allows to get cases to fill kanban view within FE",  # TODO:
        parameters=[
            OpenApiParameter(
                name="started_after",
                description="Shows only investigations/cases created after given date/datetime",  # TODO?
                type=datetime,
                examples=[
                    OpenApiExample("2020-11-24", value="2020-11-24"),
                    OpenApiExample("2021-06-28T20:23:37", value="2021-06-28T20:23:37"),
                    OpenApiExample('2023-06-28T20:25:11.248244+00:00', value="2023-06-28T20:25:11.248244+00:00"),
                ],
                required=False,
            )
        ],
    ),
)
class KanbanView(ListAPIView):

I just want to add an extra response for http 400 like this:

@extend_schema_view(
    get=extend_schema(
        operation_id='Kanban endpoint',  # TODO:
        description="Allows to get cases to fill kanban view within FE",  # TODO:
        parameters=[
            OpenApiParameter(
                name="started_after",
                description="Shows only investigations/cases created after given date/datetime",  # TODO?
                type=datetime,
                examples=[
                    OpenApiExample("2020-11-24", value="2020-11-24"),
                    OpenApiExample("2021-06-28T20:23:37", value="2021-06-28T20:23:37"),
                    OpenApiExample('2023-06-28T20:25:11.248244+00:00', value="2023-06-28T20:25:11.248244+00:00"),
                ],
                required=False,
            )
        ],
        responses={
            400: OpenApiResponse(
                description='**ACHTUNG**: You can get here VALIDATION_ERROR',  # TODO:
                response=ExceptionSerializer,
                examples=[
                    OpenApiExample(
                        "VALIDATION_ERROR",
                        value={
                            "api_status_code": "VALIDATION_ERROR",
                            "data": {
                                "detail": {
                                    "started_after": ["Enter a valid date/time."],
                                }
                            },
                        },
                    ),
                ],
            ),
        },
    ),
)
class KanbanView(ListAPIView):

to add the missing thing, but then the default http 200 response is overwritten and 400 response is the only one visible. Is there a way to add extra responses and leave automatically generated one as it was?

Thanks!

tfranzel commented 4 months ago

Hi @diego351,

short answer is no. It is designed on purpose like that. The idea is "if you take over, you take over completely". I think it shouldn't be too much hassle add one line: responses={200: YourDefaultSerializer, 400: ...}

Rationale: There are cases when you want to, for example, switch out a detected 200 with a 201. This gets too complicated quickly when mixing and matching imho. The logic you just asked for would make this more difficult to understand. Sure, it would be possible, but I opted against it a long time ago and now we cannot touch it anymore anyway because it would break the majority of the userbase.

If you want to add the 400 systemically, I would recommend overriding the get_response_serializer in a custom AutoSchema class: https://github.com/tfranzel/drf-spectacular/blob/1dbb6c146c316497186fe2978af7c74310484507/drf_spectacular/openapi.py#L371