DRF (django-rest-framework) action decorator not working

1190 views python
-1

I have this class view, that works perfectly for creating and listing objects of SiteGroup:

But I need a method to perform several operations on a single SiteGroup object, and objects associated with them. Therefore, I have tried to create a method, decorated with @action (as suggested by the docs).

According to the docs, this will autogenerate the intermediate url. Nevertheless, it doesn't work.

When I try to access (given that 423 is an existing SiteGroup Object):

http://127.0.0.1:8000/api/site-groups/423/replace_product_id/?product_id=0x345

the url is not found.

I also tried generating myself the URL in the urls.py, with no luck.

Can someone tell me where the problem is? I've browsed through all the docs, and found no clue. Thanks a lot.

class SiteGroupDetail(generics.ListCreateAPIView):
    queryset = SiteGroup.objects.all()
    parser_classes = (MultiPartParser, FormParser, JSONParser)
    serializer_class = SiteGroupSerializer
    authentication_classes = (authentication.TokenAuthentication,)

    @action(detail=True, methods=['post'], url_path='replace_product_id', permission_classes=[IsSuperUser], url_name='replace_product_id')
    def replace_product_id(self, request, pk=None, device_type=None):
        serializer = SiteGroupSerializer(data=request.data)
        product_id = self.request.query_params.get('product_id', None)
        print("replace_product", product_id, device_type, pk, flush=True)
        return Response({"hello":product_id})

My urls.py

from django.conf.urls import url, include

from api import views, routers

router = routers.OptionalSlashRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),

    url(r'^site-groups/$', views.SiteGroupList.as_view()),
    url(r'^site-groups/(?P<pk>[0-9]+)/$', views.SiteGroupDetail.as_view()),

]

And OptionalSlashRouter:

from rest_framework.routers import SimpleRouter


class OptionalSlashRouter(SimpleRouter):

    def __init__(self):
        self.trailing_slash = '/?'
        super(SimpleRouter, self).__init__()

answered question

1 Answer

11

For one thing the router should be calling

super(OptionalSlashRouter, self).__init__()

What you have now calls __init__ of SimpleRouter's parent, skipping the logic in SimpleRouter.__init__

Change that and see if it starts working

Actually as you're using python 3 it could be just

super ().__init__()

posted this

Have an answer?

JD

Please login first before posting an answer.