Pass extra parameter to custom actions

Viewed 3257

Hi I have a custom action in my viewset, but beyond detail=True, Im not sure how to add more arguments to the route I want to make an action to filter doctors from a certain category, the url should be something like doctor/categories/<int:category_id> but Im getting a Page not found (404) when trying to add the argument

  @action(detail=False, methods=['get'])
    def categories(self, request,*args, **kwargs):
        """ 
        Get a list of doctor profiles from an specific category 
        """


        data = {
            'profile' : 'doctor',
        }
        return Response(data, status=status.HTTP_200_OK)

EDIT--

when trying something like this

@action(detail=False, methods=['get'], url_path='categories/<int:category_id>')
    def categories(self, request,*args, **kwargs):

Im still getting error 404 and when checking the available routes I find this

v1/ ^profiles/doctors/categories/<int:category_id>/$ [name='profiles/doctors-categories']

v1/ ^profiles/doctors/categories/<int:category_id>\.(?P<format>[a-z0-9]+)/?$ [name='profiles/doctors-categories']

So the url is there... but maybe somehow Im typing it wrong?

this is my url

http://127.0.0.1:8000/v1/profiles/doctors/categories/1

This is my urls.py (simplyfied)

from sanitas.views import doctor_schedule as doctor_schedule_views

router = DefaultRouter()

router.register(r'profiles/doctors', doctor_profiles_views.DoctorProfileViewset, basename='profiles/doctors')


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

I hope you guys can help me

2 Answers

From the DRF doc of Routing for extra actions

By default, the URL pattern is based on the method name, and the URL name is the combination of the ViewSet.basename and the hyphenated method name. If you don't want to use the defaults for either of these values, you can instead provide the url_path and url_name arguments to the @action decorator.

So, use url_path as,

@action(detail=False, methods=['get'], url_path=r'categories/(?P<category_id>\d+)')
def categories(self, request, *args, **kwargs):
    return Response({'msg': 'ok', 'kwargs': kwargs})

Now use the end-point: /profiles/doctors/categories/1234/

Note: the url_path value must be in a regex compatible string, DRF won't recognise if it is a path compatible string

you need to change your url_path value to

url_path=r'categories/(?P<category_id>\d+)' 

instead of

url_path=r'categories/<category_id>)'

and you need category_id parameter in your action

@action(detail=False, methods=['get'], url_path=r'categories/(?P<category_id>\d+)')
def categories(self, request,category_id, *args, **kwargs):
#here you can access your category_id param
return Response(...)
Related