question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@extend_schema has no effect on GET/retrieve extra actions in a ModelViewSet

See original GitHub issue

DRF v3.11.1 drf-spectacular v0.15.0

When adding an extra GET action (not merely overriding create or retrieve) in a ModelViewSet and decorating it with @extend_schema, the specified request serializer is not represented as a component in the generated schema.

In the example below, the search/ endpoint shows up under paths, but the fields under SearchRequestSerializer are not included under components/schemas. Changing the action to a POST method instead of a GET resolves the issue, but I believe the method really should be a GET.

Example View and method:

  class MyObjectViewSet(viewsets.ModelViewSet):

    http_method_names = ['get', 'post']
    serializer_class = MyObjectSerializer

    
    @sensitive_variables('access_token')
    @extend_schema(
        request=SearchRequestSerializer,
        responses={
            (200,'application/gzip'): OpenApiTypes.BINARY,
            401: OpenApiResponse(response=GeneralResponseSerializer),
            404: OpenApiResponse(response=GeneralResponseSerializer)
        },
    )
    @action(detail=False, methods=['GET'])
    def search(self, request):
      data = SearchRequestSerializer(data=self.request.query_params)
      data.is_valid(raise_exception=True)

      ...

      return response

Excerpt from the generated schema (as a GET):

paths:
/api/documents/search/:
    get:
      operationId: documents_search_retrieve
      tags:
      - documents
      security:
      - basicAuth: []
      - tokenAuth: []
      - {}
      responses:
        '200':
          content:
            application/gzip:
              schema:
                type: string
                format: binary
          description: ''
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeneralResponse'
          description: null
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeneralResponse'
          description: null

Excerpt from the generated schema (if I change it to a POST):

  /api/documents/search/:
    post:
      operationId: documents_search_create
      tags:
      - documents
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SearchRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/SearchRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/SearchRequest'
        required: true
      security:
      - basicAuth: []
      - tokenAuth: []
      - {}
      responses:
        '200':
          content:
            application/gzip:
              schema:
                type: string
                format: binary
          description: ''
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeneralResponse'
          description: null
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GeneralResponse'
          description: null

...

components:
  schemas:
    SearchRequest:
      <details from the SearchRequest serializer>

I would expect a componentcalled SearchRequest to be included in the schema, along with the field metadata defined in SearchRequestSerializer.

I realize I may be misunderstanding the expected behavior here. If so, I could really use a pointer in the right direction.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
cantus-firmuscommented, Oct 3, 2022

Yes it does- thank you very much! I didn’t understand the distinction between the request and parameters args and how they correlate to the HTTP structures.

I assumed versions would be more tightly coupled, but I’ll go ahead and update in my dev environment today.

Thanks for your help!

0reactions
tfranzelcommented, Oct 3, 2022

Thanks for the reply. Updating to a newer release of drf is in our roadmap.

you can update spectacular regardless. Our latest version supports DRF>=3.10.4 which is clearly the case for your DRF version.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Viewsets - Django REST framework
A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post() ,...
Read more >
Django Rest Framework - unit testing viewset extra actions
It should be tested like any other endpoint, except it has a different URL. For example, I have a endpoint to allow users...
Read more >
django-rest-framework/viewsets.py at master - GitHub
This method will noop if `detail` was not provided as a view initkwarg. The base ViewSet class does not provide any actions by...
Read more >
Django REST Framework Views - ViewSets - TestDriven.io
ReadOnlyModelViewSet is a ViewSet that provides only list and retrieve actions by combining GenericViewSet with the RetrieveModelMixin and ...
Read more >
10 things you need to know to effectively use Django Rest ...
In this article I want to share some ideas and tricks that I got to know while working with Django Rest Framework in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found