Reputation: 3968
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/
?
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.
Upvotes: 1
Views: 1873
Reputation: 23024
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
Upvotes: 2