Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 12111

Mapping DRF GenericViewSet to http verbs via DefaultRouter

$
0
0

My goal is to implement adding a recipe to current user favorites list and removing it using Django Rest Framework 3.12.x.

POST api/recipes/{int:recipe_id}/favoriteDELETE api/recipes/{int:recipe_id}/favorite

Request body is empty. User_id is got from self.context['request'].user.id.

I.e. I need to serve POST and DELETE on the same URL.

I implemented that against DefaultRouter in conjunction with GenericViewSet, but can't get this implementation serving DELETE. Only POST is served properly.

The quesrtion is: what's wrong in the configuration? Why DRF returns 405 "Method Not Allowed" on DELETE calls and returns Http header Allow: POST, OPTIONS?

Router configuration:

from rest_framework import routersfrom api.views import FavoriteViewSet_v1_router = routers.DefaultRouter()_v1_router.register(    r'recipes/(?P<recipe_id>\d+)/favorite',    FavoriteViewSet,    basename='favorite')

View:

class FavoriteViewSet(    mixins.CreateModelMixin,    mixins.DestroyModelMixin,    viewsets.GenericViewSet):permission_classes = (IsAuthenticated,)http_method_names = ('post', 'delete', 'head', 'options',)queryset = Favorite.objects.all()serializer_class = FavoriteSerializerpagination_class = Nonedef get_permissions(self):    return super().get_permissions()def get_object(self):    return super().get_object()def retrieve(self, request, *args, **kwargs):    instance = self.get_object()    serializer = self.get_serializer(instance)    return Response(serializer.data)def destroy(self, request, *args, **kwargs):    super().destroy(request, *args, **kwargs)def get_serializer_class(self):    return super().get_serializer_class()def dispatch(self, request, *args, **kwargs):    p1 = hasattr(self, 'get')    p2 = hasattr(self, 'post')    p3 = hasattr(self, 'delete')    p4 = hasattr(self, 'options')    return super().dispatch(request, *args, **kwargs)

Having spent some time in the Debugger, I figured out, that router configures two instances of my View, but serves request each time on the first one.

def as_view(cls, actions=None, initkwargs) - got called twice during initialization.With parameters:

post: createsuffix: List, basename: favorite, detail: Falseget: retrieve, delete: destroysuffix: Instance, basename: favorite, detail: True

I see,that something is wrong with configuration, but couldn't figure out yet how to make DELETE request to the same URL being served on the second instance.

Under the Debugger I see that in dispatch:

def dispatch(self, request, *args, **kwargs):    p1 = hasattr(self, 'get')    p2 = hasattr(self, 'post')    p3 = hasattr(self, 'delete')    p4 = hasattr(self, 'options')    return super().dispatch(request, *args, **kwargs)

On picked view instance only p2 and p4 are True, so, view does not see 'delete' attribute presense in my view and rejects the request with 405.


Viewing all articles
Browse latest Browse all 12111

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>