1

I try to return a list of select options for countries using django-countries and django rest framework. I use JWT_AUTH for the authentication.

When I try a options request:

curl \
  -H "Authentication: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFsYmVydG9fdmVudGEiLCJ1c2VyX2lkIjoyLCJlbWFpbCI6IiIsImV4cCI6MTUwODE2Mzg4Mn0.svxqTThCahSl1Vu27sMjuJyd1PRLk28-Xgn2OKKb5-g"\
  -X OPTIONS \
  -v http://127.0.0.1:8000/api/v1/core/perfilViajeroUserPass/

The response is:

{
 "name":"Perfil Viajero User Pass Create",
 "description":"",
 "renders":["application/json","text/html"],
 "parses":[
           "application/json",
           "application/x-www-form-urlencoded",
           "multipart/form-data"
          ]
}

But I think that it should be something like this by default:

{
"name": "To Do List",
"description": "List existing 'To Do' items, or create a new item.",
"renders": [
    "application/json",
    "text/html"
],
"parses": [
    "application/json",
    "application/x-www-form-urlencoded",
    "multipart/form-data"
],
"actions": {
    "POST": {
        "note": {
            "type": "string",
            "required": false,
            "read_only": false,
            "label": "title",
            "max_length": 100
        }
    }
}

}

Someone could help me? thanks.

luistm
  • 1,027
  • 4
  • 18
  • 43
Alberto Diaz
  • 113
  • 1
  • 1
  • 9

4 Answers4

2

Adding another answer since I recently ran into the same issue and found it a bit mystifying -- when making an OPTIONS request, Django Rest Framework uses the view's Metadata class to construct a response. The default Metadata class is SimpleMetadata, as mentioned in the docs. However, SimpleMetadata only adds the actions key to the response body if the view in question defines the method get_serializer(). I'm not sure why this is the case, but see here for the relevant code.

rest_framework.generics.GenericAPIView defines a get_serializer() method, so (authenticated) OPTIONS requests made to these views will return a response body with the actions key. But rest_framework.views.APIView does not define this method, so the actions key will always be absent.

If you have to use rest_framework.views.APIView, you could work around this by defining a get_serializer() method on your APIView class. Which feels a little hacky, but I tested it and it works:

class MyView(views.APIView):
    def get_serializer(self):
        return MySerializer()

    def post(self):
        ...
Samira N
  • 103
  • 1
  • 8
  • I believe it's because `APIView` has no `serializer_class` attribute out of the box either, although you can add one if you want to enable browsable API forms for `APIView` views. It could also be because the method in `SimpleMetadata` needs access to the view's serializer, and because there's no `serializer_class` attribute nor a method `get_serializer` implemented, there's no easy way to determine this from the separate class. That portion could definitely use a rewrite though imo. It's a small but important issue that's hard to catch unless you're looking for it. – wjh18 Jul 19 '23 at 03:12
1

If you want to change some of the content:

  • name is the view's get_view_name which is the view's name slightly reworked.
  • description is the view's get_view_description which reworks the view's docstring.

Otherwise if you want something more complex, you'll probably want to customize the view's metadata as explained in http://www.django-rest-framework.org/api-guide/metadata/#custom-metadata-classes

Linovia
  • 19,812
  • 4
  • 47
  • 48
  • but the documentation says that actions are included by default: 'Here's an example response that demonstrates the information that is returned by default.' http://www.django-rest-framework.org/api-guide/metadata/ – Alberto Diaz Nov 06 '17 at 08:19
  • Then either there's something wrong in your view, either you don't have the required permission to perform the action. – Linovia Nov 06 '17 at 08:26
  • I have added permission_classes = (AllowAny,) to my view so I dont know where the error is – Alberto Diaz Nov 06 '17 at 10:10
0

I have found the solution.

I change my view class type from APIView to generics.CreateAPIView and know it works. Thank you very much.

Alberto Diaz
  • 113
  • 1
  • 1
  • 9
0

Another reason an OPTIONS response doesn't contain the actions list is if the view doesn't allow the PUT or POST methods.

See SimpleMetadata.determine_actions() in the DRF source rest_framework/metadata.py.