In Django Rest Framework is it possible to have a custom method in an APIView
class be called similar to how .get()
or .post()
would be called.
I know it's possible with routers using the @action()
or @link()
decorators, I'm trying to figure out if you can do something similar to an APIView
but have it so I can set the method to whatever url I want.
I've tried decorating the class with @action()
and @api_view()
but nothing seems to have worked.
I'm not exactly sure what I should put in the url for an endpoint to actually call the method in the class. Would I use CartAPIView.clear.as_view()
, CartAPIView.clear
, or CartAPIView.clear()
. I've tried different combinations of calls to CartAPIView
but nothing has worked.
Here's an example of what I'm trying to do:
# views.py
class CartAPIView(APIView):
@api_view(['POST'])
def clear(self, request):
"""Clear the users cart."""
queryset = Cart.objects.get(user=request.user)
queryset.clear_cart()
serializer = CartSerializer(queryset)
return Response(serializer.data, status=status.HTTP_200_OK)
# urls.py
urlpatterns = patterns('app.views',
....
url(r'^cart/clear/$', CartAPIView.clear.as_view(), name='clear_cart_api'),
....
)
Any help would be appreciated.
You seem to miss the point of how a class-based view's flow works.
as_view
handles that by creating an unbound function, and in that function instantiating the class-based
view. as_view
then calls self.dispatch(request, *args, **kwargs)
, where self
is the instantiated object that's just created.dispatch
calls either self.get(request, *args, **kwargs)
or self.post(request, *args, **kwargs)
, depending on the request method (or put
, patch
or delete
if those are allowed and used). There's no room for a custom function like your clear
function, unless you override one of these methods to call self.clear(request)
. The equivalent of @api_view(['POST'])
would be to override the post(request, *args, **kwargs)
method:
# views.py
class CartAPIView(APIView):
def post(self, request, *args, **kwargs):
# Why would you call this 'queryset'? It's a single object.
cart = Cart.objects.get(user=request.user)
cart.clear_cart()
serializer = CartSerializer(cart)
return Response(serializer.data, status=status.HTTP_200_OK)
# urls.py
urlpatterns = patterns('app.views',
url(r'^cart/clear/$', CartAPIView.as_view(), name='clear_cart_api'),
)
It seems what you are looking for is Function Based Views, where you can decorate a function with @api_view()
from rest_framework.decorators import api_view
@api_view(['POST'])
def clear(request):
"""Clear the users cart."""
queryset = Cart.objects.get(user=request.user)
queryset.clear_cart()
serializer = CartSerializer(queryset)
return Response(serializer.data, status=status.HTTP_200_OK)
# urls.py
urlpatterns = patterns('app.views',
....
url(r'^cart/clear/$', 'clear', name='clear_cart_api'),
....
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With