How to remove/prevent parameters inherited" from ViewSet
See original GitHub issueI am migrating from drf_yasg
to drf-spectacular
and I think the below is not answered yet anywhere. I did read the docs 😃
I have some ViewSets to handle models via DRF, for example:
class EngagementViewSet(mixins.ListModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.CreateModelMixin,
ra_api.AcceptedRisksMixin,
viewsets.GenericViewSet):
serializer_class = serializers.EngagementSerializer
queryset = Engagement.objects.none()
filter_backends = (DjangoFilterBackend,)
filter_class = ApiEngagementFilter
permission_classes = (IsAuthenticated, permissions.UserHasEngagementPermission)
@swagger_auto_schema(
request_body=no_body, responses={status.HTTP_200_OK: ""}
)
@extend_schema(
request=no_body,
responses={status.HTTP_200_OK: ""}
)
@action(detail=True, methods=["post"])
def close(self, request, pk=None):
eng = self.get_object()
close_engagement(eng)
return HttpResponse()
As you can see there is a custom Mixin ra.api.AcceptedRisksMixin
to provides an extra action method:
class AcceptedFindingsMixin(ABC):
@swagger_auto_schema(
request_body=AcceptedRiskSerializer(many=True),
responses={status.HTTP_201_CREATED: RiskAcceptanceSerializer(many=True)},
)
@extend_schema(
request=AcceptedRiskSerializer(many=True),
responses={status.HTTP_201_CREATED: RiskAcceptanceSerializer(many=True)},
)
@action(methods=['post'], detail=False, permission_classes=[IsAdminUser], serializer_class=AcceptedRiskSerializer)
def accept_risks(self, request):
serializer = AcceptedRiskSerializer(data=request.data, many=True)
if serializer.is_valid():
accepted_risks = serializer.save()
else:
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
owner = request.user
accepted_result = []
for engagement in get_authorized_engagements(Permissions.Engagement_View):
base_findings = engagement.unaccepted_open_findings
accepted = _accept_risks(accepted_risks, base_findings, owner)
engagement.accept_risks(accepted)
accepted_result.extend(accepted)
result = RiskAcceptanceSerializer(instance=accepted_result, many=True)
return Response(status=201, data=result.data)
For drf-yasg
it works as expected/desired, getting two parameters the id
and request body in the schema:
"/api/v2/engagements/{id}/accept_risks/": {
"post": {
"operationId": "engagements_accept_risks_create",
"description": "",
"parameters": [
{
"in": "path",
"name": "id",
"schema": {
"type": "integer"
},
"description": "A unique integer value identifying this engagement.",
"required": true
}
],
"tags": [
"engagements"
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AcceptedRisk"
}
},
For drf-spectacular
I am getting a lot more parameters. I think these are “inherited” or discovered from the EngagementViewset where there is a filter backend that accepts all these parameters.
"/api/v2/engagements/{id}/accept_risks/": {
"post": {
"operationId": "engagements_accept_risks_create",
"description": "",
"parameters": [
{
"in": "query",
"name": "active",
"schema": {
"type": "boolean"
}
},
{
"in": "query",
"name": "api_test",
"schema": {
"type": "boolean"
}
},
{
"in": "path",
"name": "id",
"schema": {
"type": "integer"
},
"description": "A unique integer value identifying this engagement.",
"required": true
},
{
"in": "query",
"name": "id",
"schema": {
"type": "integer"
}
},
{
"name": "limit",
"required": false,
"in": "query",
"description": "Number of results to return per page.",
"schema": {
"type": "integer"
}
},
....
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AcceptedRisk"
}
}
},
I also notice pagination related schema elements in the response:
"responses": {
"201": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedRiskAcceptanceList"
}
}
},
"description": ""
}
}
Is the expected / intended behaviour? Without stating which one is correct, I think the drf-yasg
scheme is what I was expecting / looks the most intuitive.
I tried using @extend_schema
, but it looks like that can only be used to add extra parameters, not to remove superfluous ones.
Is there anyway to prevent this “inheritance” of parameters and other elemens into the method from the MixIn?
I am not seeing all these “extra parameters” on @action methods declared directly in the ViewSet, such as close
in the above example.
Full code is at: https://github.com/valentijnscholten/django-DefectDojo/blob/cd89dac2d92f5734c7c717edce39130caf6278f3/dojo/api_v2/views.py#L115
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (4 by maintainers)
Small tweak to use empty list needed as
filter_backends=None
caused some issues down the road:yes that makes sense. i wrote that example from memory. django-filter depends on both classes. perfect!