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',
)
}
Related
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]
I have the following in my views.py
I've been reading the documentation and trying to work out is there a way to exclude certain endpoints for this view.
from EoX.models import Vendor
from rest_framework import viewsets
from rest_framework import permissions
from .serializers import VendorSerializer
from url_filter.integrations.drf import DjangoFilterBackend
from drf_yasg.utils import swagger_auto_schema
from django.utils.decorators import method_decorator
class VendorViewSet(viewsets.ModelViewSet):
queryset = Vendor.objects.all()
serializer_class = VendorSerializer
permission_classes = [permissions.AllowAny]
filter_backends = [DjangoFilterBackend]
filter_fields = ['name',]
I can exclude the view all together with
schema=None
I tried decorating it with
#method_decorator(name='list', decorator=swagger_auto_schema(
operation_description="description from swagger_auto_schema via method_decorator"
))
and that changes the description of the 'get' endpoint.
but trying
#method_decorator(name='list', decorator=swagger_auto_schema(methods=['get'],
operation_description="description from swagger_auto_schema via method_decorator"
))
throws an error
AssertionError:methodormethodscan only be specified on #action or #api_view views
Is this a bug? or just not a supported feature, and is there a way to accomplish what I am trying?
Many thanks.
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
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)
I'm trying to set custom permissions on a class that extends viewsets.ModelViewSet and it appears that my permissions are not being evaluated. Here is my view:
from rest_framework import viewsets
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
import models
import serializers
from permissions import IsAdminOrAuthenticatedReadOnly
class KPIViewSet(viewsets.ModelViewSet):
'''
API endpoint that allows KPI metadata to be viewed or edited
'''
authentication_classes = (BasicAuthentication,)
permission_classes = (IsAdminOrAuthenticatedReadOnly,)
queryset = models.KPI.objects.all()
serializer_class = serializers.KPISerializer
And here is my permission class:
from rest_framework.permissions import BasePermission, SAFE_METHODS
class IsAdminOrAuthenticatedReadOnly(BasePermission):
def has_permissions(self, request, view):
if request.method in SAFE_METHODS:
return request.user and request.user.is_authenticated()
return request.user and request.user.is_staff()
The problem I'm running into is that IsAdminOrAuthenticatedReadOnly never seems to get evaluated. I tested this both by forcing it to always return "False" and by switching the permission_classes value to "IsAuthenticated" in the view. In the former scenario, a request to the endpoint returns as if there were no authentication requirement. In the later, authentication is enforced as expected.
Any ideas what I'm missing?
The method name is has_permission not has_permissions (no s) ;)