Support annotating a `PATCH` `@action` with `@extend_schema` to use `PatchedTRequest`
Opened this issue · 3 comments
I have an @action
of the form:
@action(
methods=[HTTPMethod.PATCH],
detail=False,
url_path="bulk-partial-update",
)
def bulk_partial_update(self, request: Request) -> Response:
...
And a ViewSet
of the form:
@extend_schema_view(
bulk_partial_update=extend_schema(
request=TSerializer(many=True), responses=TSerializer(many=True)
),
)
class TViewSet(ModelViewSet):
queryset = T.objects.all()
...
I was hoping that because the @action
was tagged as HTTPMethod.PATCH
that drf-spectacular
would automatically use the PatchedTRequest
form of the generated T
for the request
side of the API since PATCH
is used in HTTP for partial updates.
But when I looked at the generated OpenAPI spec, I found it looked like:
/T/bulk-partial-update/:
patch:
operationId: t_bulk_partial_update_partial_update
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/TRequest'
required: true
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/T'
description: ''
Specifically I was hoping that requestBody
would use PatchedTRequest
.
This code seems relevant to this issue
drf-spectacular/drf_spectacular/plumbing.py
Lines 170 to 176 in a79bc5d
I was able to manually add partial=True
to work around this.
@extend_schema_view(
bulk_partial_update=extend_schema(
request=TSerializer(many=True, partial=True), responses=TSerializer(many=True)
),
)
So the only issue I have remaining is that for bulk partial updates, I need to have the required id
present, but all other fields marked optional. partial=True
solves the part of making all fields optional, but is there any clean way to also describe "even for this request, the id
field must exist"?
As an example of what the partial update data looks like:
[
{"id": 1, "name": "fred"},
{"id": 2, "age": 10}
]