Let's say I have a DRF viewset like so
class SecretViewset(
viewsets.ModelViewSet,
):
queryset = Secret.objects.all()
serializer_class = SecretSerializer
@action(methods=['GET'], detail=True)
def name(self, request, pk=None):
secrets = Secret.objects.filter(name__contains=pk)
return Response(self.get_serializer(secrets, many=True).data)
I want to be able to search via a name in the URL. So /api/secrets/name/NAMEHERE/
However, because ModelViewset implements mixins.Retrieve
, it returns a 404 because it searches /api/secrets/ID/
first and doesn't find it, therefore throws a 404.
What would the proper way be to go about adding the ability to search by name as described above?
Edit
Adding my urls conf
from .Secret.viewsets import SecretViewset
router = routers.SimpleRouter()
router.register(r'^api/secrets', SecretViewset, 'secrets')
# Later on, router gets imported and added on via `urlpatterns = router.urls`
CodePudding user response:
in yor urls.py put /api/secrets/name/NAMEHERE/ before /api/secrets/ID/
CodePudding user response:
You can do this using a simple APIView and a custom url path.
Code for the view:
class SecretRetrieveView(rest_framework.views.APIView):
def get(self, request, *args, **kwargs):
secrets = Secret.objects.filter(name__contains=kwargs['name'])
return Response(SecretSerializer(secrets, many=True).data)
Code in your urls config: (Don't forget to import SecretRetrieveView!)
custom_urlpatterns = [
path('/api/secrets/name/<str:name>/', SecretRetrieveView.as_view(), name='secret-retrieve'),
]
Finally, Make sure your urls conf looks like this
urlpatterns = custom_urlpatterns
urlpatterns = router.urls