I’m creating a site that has Django Rest Framework as its backend and ReactJS as its frontend. I have multiple api-endpoints for various data, i.e.
/api/ /api/users/ /api/objects/ /api/other_objects/ etc
I don’t want regular users to have direct access to the DRF interface. If anyone decides to go to one of those urls, I’d prefer to redirect them to the index page if they don’t have staff status.
I tried to redirect users using decorators in views:
from django.contrib.auth.decorators import user_passes_test def staff_check(user): if user.is_authenticated and user.is_staff: return True else: return False @user_passes_test(staff_check, login_url='/', redirect_field_name=None) @api_view(['GET']) def api_root(request, format=None): return Response({ 'users': reverse('user-list', request=request, format=format), 'objects': reverse('objects-list', request=request, format=format), 'other_objects': reverse('other-objects-list', request=request, format=format) })
It works fine as far as redirection goes, but when my React app tries to fetch data from endpoints with decorators, it gets redirected as well.
I know that I can instead set permissions on the views, i.e.
class ObjectsList(generics.ListCreateAPIView): queryset = Object.objects.all().order_by('created') serializer_class = ObjectSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
However it still allows users to view the interface (with or without content, dependent on the permissions). Is there a way to keep endpoints accessable to React’s fetch command without redirection, but still redirect users, when they try to view the interface?
Advertisement
Answer
Just change your renderer class and remove default BrowsableAPIRenderer
from list.
Globally, like this:
REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( 'rest_framework.renderers.JSONRenderer', ) }
But in your case, you could control it per view using decorator (when the interface should or not show up):
@api_view(['GET']) @renderer_classes((JSONRenderer, BrowsableAPIRenderer)) def your_view(request, format=None): ...