I recently started working with Django backend development, so I'm still struggling with some features. This time, I've encountered a problem that has been quite challenging, and I couldn't find any helpful answers on the web. I'm creating a view that supports both 'GET' and 'POST' requests. The issue I'm facing is that while I need a Bearer token for the 'POST' request, I don't want to require a token for the 'GET' request. Initially, I considered creating a separate view just for the 'GET' request, but that seemed redundant. Then, I came across the 'IsAuthenticatedOrReadOnly' permission class in the Django Rest Framework documentation. I thought this would solve my problem, but even after implementing this verification, the 'GET' endpoint still asks for a token. Could someone please provide me with some insights?
Here's my view:
from rest_framework.views import Request, Response, status, APIView
from .serializers import MovieSerializer
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from movies.models import Movie
class MovieView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticatedOrReadOnly]
def post(self, request: Request) -> Response:
serializer = MovieSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save(user = request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
def get(self, request: Request) -> Response:
movies = Movie.objects.all()
serializer = MovieSerializer(movies, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
...and in case you need... here's my model:
from django.db import models
# Create your models here.
class MovieRating(models.TextChoices):
G = 'G'
PG = 'PG'
PG13 = 'PG-13'
R = 'R'
NC17 = 'NC-17'
class Movie(models.Model):
title = models.CharField(max_length=127)
duration = models.CharField(max_length=127, blank=True, null=True, default=None)
rating = models.CharField(max_length=20, choices=MovieRating.choices, default=MovieRating.G)
synopsis = models.TextField(blank=True, null=True, default=None)
user = models.ForeignKey(
"users.User",
on_delete=models.CASCADE,
related_name="movies",
default=None
)
You can override the get_permissions
class based on the request made. The example below works with ModelViewSet.
def get_permissions(self):
if self.action in ['list', 'retrieve']:
# Get requests
return (permissions.AllowAny(),)
else:
# Any other request
return (permissions.IsAuthenticated(),)