1

I am currently writing a POST request to create an A record:

client.post(url, {'name' : 'foo', 'another_field' : 2})

And on the server side, on the view, I have:

class AQuery(generics.GenericAPIView):
    queryset = A.objects.all()
    serializer_class = ASerializer

    def get(self, request, param1, param2, format=None):
        ... # do some special query based off of param1 and 2.

    def post(self, request, format=None):
        serializer = self.get_serializer(data=request.data, many=False) 
        if serializer.is_valid():
            serializer.save()
            return Response(...)
        return Response(...)

As you can see, I want param1 and param2 to be captured in the url, and so in the urls.py:

urlpatterns = [
    # for GET
    path('A/<str:param1>/<path:param2>', views.AQuery.as_view(), name='A query GET')
    # for POST
    path('A', views.AQuery.as_view(), name='A query POST')
    ...
]

Obviously, I can add the param1 and param2 to the post function def, but they would just be there, with no purpose. Seems like bad code smell to me.

How would I implement something like this, and explicitly disallow the client to make a POST request to A/param1/param2, and explicitly disallow the client to make a GET request to A/?

What I've tried

I tried to turn the View into a viewsets.ModelViewSet, and added the following:

a_get_query = AQuery.as_view({'get':'get'})
a_post_query = AQuery.as_view({'post':'post'})

and in my urls.py:

urlpatterns = [
        # for GET
        path('A/<str:param1>/<path:param2>', views.a_get_query, name='A query GET')
        # for POST
        path('A', views.a_post_query, name='A query POST')
        ...
    ]

But I get the following error:

TypeError: The actions argument must be provided when calling .as_view() on a ViewSet. For example .as_view({'get': 'list'})

and I'm not quite sure where it's happening.

1 Answer 1

2

This approach works as expected for me. I had to make a couple of minor changes however:

1) I had to change the names of the functions from get and post to do_get and do_post. Django seems to do something special when the functions are named the same as the HTTP methods themselves.

2) I inlined calling as_view() directly in the urls.py.

So after doing that:

urlpatterns = [
        # for GET
        path('A/<str:param1>/<path:param2>', views.AQuery.as_view({'get':'do_get'}), name='A query GET')
        # for POST
        path('A', views.AQuery.as_view({'post':'do_post'}), name='A query POST')
        ...
    ]

The result:

GET   A/param1/param2  -> 200 OK
GET   A/               -> 405 Method Not Allowed

POST  A/param1/param2  -> 405 Method Not Allowed
POST  A/               -> 200 OK
Sign up to request clarification or add additional context in comments.

1 Comment

I tried inlining it and renaming it and realized that the issue was gone for some reason. Though I'm not sure what the reason is, I have accepted your answer :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.