How to hide POST form in Django REST framework? - django

I have Django REST framework form like this:
and I would like to do a simple thing: hide POST form (in the red rectangle) when the user is not logged in. I just don't know how to do it, because all I have is model, view that inherits from ListCreateAPIView and serializer inhgeriting from ModelSerializer.

You can use Django rest framework Authentication and Permission classes: https://www.django-rest-framework.org/api-guide/authentication/

from rest_framework.permissions import IsAuthenticated
if you use generic or viewsets class add this line inside your view class
permission_classes = [IsAuthenticated]
or you can set permission to admins only by import
from rest_framework.permissions import IsAdminUser
and
permission_classes = [IsAdminUser]

Related

DRF APIview with authentication

I have a class someAPI(APIView). I would like this one to be accessed by only authorised users.
I tried this link How to use login_required in django rest view
and
https://www.django-rest-framework.org/api-guide/authentication/
but none of them seem work.
My current authentication protocol is logging in with username and password. I guess a reason is because I implement this authentication with basic django (https://docs.djangoproject.com/en/3.1/topics/auth/default/) but not DRF.
from rest_framework.views import APIView
from rest_framework import authentication, permissions
from django.http import JsonResponse
class APICostAnalysisController(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
""" Initiate get API for getting cost analysis """
return JsonResponse(APICostAnalysisImpl().get(), safe=False,json_dumps_params={'indent': 2})

How to send POST requests to Django Rest Framework without authentication?

I want to create a POST request from React to DRF for a normal search functionality: ANYONE on the site can input something in a search field and that data will be used to query the database. I do not need the users to be authenticated or anything. In DRF there needs to be an authentication class and I dont know which one to use. Any ideas?
Set permission_classes and authentication_classes to empty
from rest_framework.views import APIView
class MyPublicView(APIView):
permission_classes = []
authentication_classes = []
You can use any DRF view instead of APIView. This procedure is same for all CBVs in DRF.

How to use GraphQL customized Authentication class?

With Django REST Framework(DRF) I can customize Authentication class and Permission class simply like this
from django_cognito_jwt import JSONWebTokenAuthentication
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
class CognitoQuestionViewSet(viewsets.ModelViewSet):
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticated,)
queryset = Question.objects.all()
serializer_class = QuestionSerializer
In the GraphQL docs. It is using standard Django login which is different from my project. I had checked with source LoginRequiredMixin but no luck. I don't see Authentication class there then I can override it
Problem:
How to customize GraphQL Authentication class and Permission class like one I did in DRF
After trials and tries with django-graphql-jwt with no luck. vinayan3 has the answer on my question. Because django-cognito-jwt is considered as a DRF complement.
Solution:
Just replace TokenAuthentication with JSONWebTokenAuthentication from django_cognito_jwt

Custom view and url for DRF

I'd like to know how to add a custom view and url using DRF.
I currently have a UserDetail(APIView) class that can display a user object using a url like /users/123/ but I'd like to also have the ability to view a users history with a url like /users/123/history/ which would likely call on a new method within the UserDetail class. Is there a way to do this?
I've tried looking through DRFs documentation and it looks like they can achieve this through ViewSets and custom Routers, but I get errors when using ViewSets likes needing to define a queryset.
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
class UserDetail(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserCreateSerializer
permission_classes = (IsAuthenticated,)
#detail_route(methods=['GET'])
def history(self, request, pk):
user= self.get_object()
serializer = UserCreateSerializer(user)
return Response(serializer.data)

Cannot apply DjangoModelPermissions when rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly is enabled

I am trying to make MongoEngine work with Django REST framework. By following this link Getting mongoengine and django rest framework to play nice, I manage to get everything working, but have to disable "PERMISSION CLASSES" in REST framework, like below
'DEFAULT_PERMISSION_CLASSES': [
#'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
Otherwise, I get this error "Cannot apply DjangoModelPermissions on a view that does not have .model or .queryset property.". The reason seems to be that the returned value from "Collection.objects" or "Collection.objects.all()" can not pass "has_permission" function in permission.py in REST framework.
Could anyone help to look at this?
Or you can just add:
from rest_framework import permissions
and in the view classes add
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
In your views.py import the following models:
from rest_framework.permissions import AllowAny
from rest_framework.decorators import api_view, permission_classes
Before declaring the function (the view function) add:
#api_view(['GET', 'POST'])
#permission_classes((AllowAny, ))
or
#api_view(['GET', 'PUT', 'DELETE'])
#permission_classes((AllowAny, ))
As per Django REST docs:
This permission class ties into Django's standard django.contrib.auth
model permissions. This permission must only be applied to views
that have a .queryset property or get_queryset() method.
This means that on your view, you must have the queryset properly set, e.g:
queryset = SampleModel.objects.all()
Best approach will be to authenticate at a view-base level. So your view must look like this:
from rest_framework.views import APIView
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
class SampleAPIView(APIView):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
permission_classes = [DjangoModelPermissionsOrAnonReadOnly,]
And just in case you are using JWT authentication, you just need to add this to settings.py:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}