'Django REST Framework - pass extra parameter to actions

I'm using Django 2.0 and Django REST Framework

I have created an action method to delete particular object from database

contacts/views.py

class ContactViewSet(viewsets.ModelViewSet):
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)

    # others actions goes here

    @action(methods=['delete'], detail=False, url_path='delete_phone/<phone_pk>/')
    def delete_phone(self, request, pk=None):
        contact = self.get_object()
        print(contact)
        print(pk)
        print(self.kwargs['phone_pk'])
        return Response({'status': 'success'})

apps/urls.py

router.register(r'contacts', ContactViewSet, 'contacts')

api_urlpatterns = [
    path('', include(router.urls)),
]

But when I access

DELETE: http://url/api/contacts/delete_phone/1/

It gives page not found error.

In the error page, there is listing in tried url patterns

api/ ^contacts/delete_phone/<phone_pk>//$ [name='contacts-delete-phone']
api/ ^contacts/delete_phone/<phone_pk>\.(?P<format>[a-z0-9]+)/?$ [name='contacts-delete-phone']


Solution 1:[1]

In case you can't/don't want/whatever install drf-nested-routers, you could achieve the same by doing:

@action(detail=True,
        methods=['delete'],
        url_path='contacts/(?P<phone_pk>[^/.]+)')
def delete_phone(self, request, phone_pk, pk=None):
    contact = self.get_object()
    phone = get_object_or_404(contact.phone_qs, pk=phone_pk)
    phone.delete()
    return Response(.., status=status.HTTP_204_NO_CONTENT)

The trick is to put the regex in url_path parameter of the decorator and pass it to the decorated method (avoid using just pk or it will collide with the first pk)

Tested with:

Django==2.0.10
djangorestframework==3.9.0

Solution 2:[2]

Perhaps this has changed since this question was asked, but this works for me in REST Framework 3.13.

@action(methods=['get'], detail=False, url_path='my_action/(?P<my_pk>[^/.]+)')
def my_action(self, request, my_pk=None):
    return Response()

Resulting in the following entry in urlconf

^my_viewset/my_action/(?P<my_pk>[^/.]+)/$ [name='my-viewset-my-action']

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Ryan