Schema generation for custom route in ModelViewSet

307 views
Skip to first unread message

Mike Helmick

unread,
Dec 6, 2017, 3:03:00 PM12/6/17
to Django REST framework
Hi,

Reached out to Tom on Twitter and was forwarded here: https://twitter.com/_tomchristie/status/938491963040501761

Could be related to:

I would like to add schema documentation for a custom method on a ModelViewSet (for drf-openapi), i.e.:

class DiscussionViewSet(ModelViewSet):
   serializer
= DiscussionSerializer
   queryset
= Discussion.objects.all()

   
def vote(self, request, version, pk):
       discussion
= self.get_queryset().get()
       vote_type
= request.POST.get('vote_type')
       
if vote_type in ['up', 'down']:
           discussion
.vote(vote_type)
       
return self.get_serializer(discussion)

Something to note:
  • I am using nested routes (that code is omitted), but I don't think that has anything to do with my issue.
If I wrap the `vote` in a `detail_route` decorator, it will show in my schema endpoint, but uses the values of my DiscussionSerializer for the request body (see attachment)

I've tried using the `schema` decorator and using AutoSchema() directly passing `manual_fields`, I've also tried overriding the `schema` on the ViewSet itself the same way:

schema = AutoSchema(manual_fields=[
        coreapi.Field(
            'vote_type',
            required=True,
            location='body',
            schema=coreschema.String(
                title='vote_type',
                description='up or down')
        )
    ])


If I DON'T use `detail_route` and only use `api_view` decorator, my endpoint fails to show in the schema at all.

Help is greatly appreciated as I've spent a good two days trying different things and searching around the internet for an answer.

Thanks!

Screen Shot 2017-12-06 at 2.59.18 PM.png

Mike Helmick

unread,
Dec 6, 2017, 3:15:28 PM12/6/17
to Django REST framework
Also, if I use the `schema` decorator and do prints on what schema is being used in decorators.py in `api_view` (in DRF)

WrappedAPIView.schema = getattr(func, 'schema',
                                        APIView.schema)

        print 'WrappedAPIView.schema', WrappedAPIView.schema
        print 'getattr schema', getattr(func, 'schema', None)

and in the `schema` decorator 

def schema(view_inspector):
    print 'view_inspector', view_inspector
    def decorator(func):
        print 'in decorator'
        func.schema = view_inspector
        print 'schema is set!', func.schema
        return func
    return decorator

It correctly accessed my custom schema (not in the post above), but didn't utilize any of the methods (get_serializer_fields), etc. that were in there. I believe the __init__ override wasn't even called. (I could be misunderstanding this part)

Mike Helmick

unread,
Dec 22, 2017, 9:48:15 AM12/22/17
to Django REST framework
I also tried a regular API view and still not seeing the fields in my schema endpoint.

views.py
from rest_framework.schemas import AutoSchema
from rest_framework.views import APIView

class CustomView(APIView):
    schema = AutoSchema(
        manual_fields=[
            coreapi.Field(
                'vote_type',
                required=True,
                location='body',
                schema=coreschema.String(
                    title='vote_type',
                    description='up or down')
            )
        ]
    )

    def get(self, request, version):
        return Response('Test.')

    def post(self, request, version):
        return Response('Test.')


urls.py (with normal url includes, etc.)
url(r'^users/$', CustomView.as_view())

See attachments for what is displayed. I expect to see a section with Request Body that has "vote_type" under it.

Screen Shot 2017-12-22 at 9.47.04 AM.png
Screen Shot 2017-12-22 at 9.47.14 AM.png
Screen Shot 2017-12-22 at 9.47.27 AM.png
Reply all
Reply to author
Forward
0 new messages