python – How to add permissions for “class UserRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView)”?

I’ve created a model using an abstract user class model class for Online flight ticket booking. I’m new to this so haven’t added many functionalities to it. I’m sharing my model.py, admin.py, serializer.py, view.py.

My question:

  1. In views.py -> class UserRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView)

I want to give access for GET PUT DELETE for only ADMIN and USER who created this profile(owner). I’m using postman to check endpoints.

“Please do check my abstract user model if there is any mistake”.

  1. permission for “BookViewSet” and “BookingRetrtieveUpdateDestroyAPIView” I only want ADMIN and USER owner who created this booking to view or modify it.

  2. I only want to get a list of passengers associated by that particular user in “PassengerListCreateAPIView(generics.ListCreateAPIView):”

#models.py


import email
from pyexpat import model
from django.db import models
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver

from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)

GENDER_CHOICES = (
    (0, 'male'),
    (1, 'female'),
    (2, 'not specified'),)

class UserManager(BaseUserManager):
  def create_user(self, email, name,contact_number,gender,address,state,city,country,pincode,dob ,password=None, password2=None):
      
      if not email:
          raise ValueError('User must have an email address')

      user = self.model(
          email=self.normalize_email(email),
          name=name,
          contact_number=contact_number,
          gender=gender,
          address=address,
          state=state,
          city=city,
          country=country,
          pincode=pincode,
          dob=dob,
          
      )

      user.set_password(password)
      
      user.save(using=self._db)
      return user

  def create_superuser(self, email, name,contact_number,gender,address,state,city,country,pincode,dob , password=None):
     
      user = self.create_user(
          email,
          
          name=name,
          contact_number=contact_number,
          gender=gender,
          address=address,
          state=state,
          city=city,
          country=country,
          pincode=pincode,
          dob=dob,
          password=password,
          
      )
      user.is_admin = True
      user.save(using=self._db)
      return user



class User(AbstractBaseUser):
    email = models.EmailField(verbose_name="Email",max_length=255,unique=True)
    name = models.CharField(max_length=200)
    contact_number= models.IntegerField()
    gender = models.IntegerField(choices=GENDER_CHOICES)
    address= models.CharField(max_length=100)
    state=models.CharField(max_length=100)
    city=models.CharField(max_length=100)
    country=models.CharField(max_length=100)
    pincode= models.IntegerField()
    dob = models.DateField()


    # is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name','contact_number','gender','address','state','city','country','pincode','dob']

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return self.is_admin

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        # Simplest possible answer: All admins are staff
        return self.is_admin


# Create your models here.
class Airport(models.Model):
    Airport_name=models.CharField(max_length=100)
    country=models.CharField(max_length=100)

    def __str__(self):
        return self.Airport_name

class Flight(models.Model):

    flight_number = models.CharField(max_length=100,unique=True)
    depart_date_time = models.DateTimeField(auto_now_add=True)
    arrival_date_time = models.DateTimeField(auto_now_add=True)
    origin = models.CharField(max_length=100, blank=True, default="")
    destination = models.CharField(max_length=100, blank=True, default="")
    price = models.IntegerField()
    airline_name = models.CharField(max_length=100, blank=True, default="")
    total_seats = models.IntegerField()
    available_seats =  models.IntegerField()
    
    
    airport=models.ForeignKey(Airport,on_delete=models.CASCADE)

    def __str__(self):
        return str(self.flight_number)

   

class Passenger(models.Model):
    name = models.CharField(max_length=100,blank=True, default="")
    contact_number= models.IntegerField()
    email = models.EmailField(max_length=254)
    
    gender = models.IntegerField(choices=GENDER_CHOICES)
    age= models.IntegerField()
    user=models.ForeignKey(User,on_delete=models.CASCADE)

    def __str__(self):
        return self.name  


class Booking(models.Model):
    user =models.ForeignKey(User,on_delete=models.CASCADE)
    flights =models.ForeignKey(Flight,on_delete=models.CASCADE)
    passenger =models.ManyToManyField(Passenger)
    booking_number= models.CharField(max_length= 100,default=0, blank= True)
    booking_time = models.DateTimeField(auto_now_add=True)
    no_of_passengers= models.IntegerField(default=0, blank= True)

    def __str__(self):
        return self.booking_number


Corresponding serializer

#serializers.py


from rest_framework import serializers
from myapp.models import Airport, Flight, User, Passenger, Booking 


class UserRegistrationSerializer(serializers.ModelSerializer):
  # We are writing this becoz we need confirm password field in our Registratin Request
  password2 = serializers.CharField(style={'input_type':'password'}, write_only=True)
  class Meta:
    model = User
    fields=['email','name','contact_number','gender','address','state','city','country','pincode','dob','password', 'password2']
    extra_kwargs={
      'password':{'write_only':True}
    }

  # Validating Password and Confirm Password while Registration
  def validate(self, attrs):
    password = attrs.get('password')
    password2 = attrs.get('password2')
    if password != password2:
      raise serializers.ValidationError("Password and Confirm Password doesn't match")
    return attrs

  def create(self, validate_data):
    return User.objects.create_user(**validate_data)

class UserLoginSerializer(serializers.ModelSerializer):
  email = serializers.EmailField(max_length=255)
  class Meta:
    model = User
    fields = ['email', 'password']

# class UserProfileSerializer(serializers.ModelSerializer):
#   class Meta:
#     model = User
#     fields="__all__"



class AirportSerializer(serializers.ModelSerializer):
    class Meta:
        model = Airport
        fields="__all__"

class FlightSerializer(serializers.ModelSerializer):
    class Meta:
        model = Flight
        fields="__all__"

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model= User
        fields="__all__"

class PassengerSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=False)
    class Meta:
        model= Passenger
        fields="__all__"

class BookingSerializer(serializers.ModelSerializer):
    class Meta:
        model= Booking
        fields="__all__"


    

#views.py



from django.shortcuts import render
from django.http import Http404, JsonResponse
#from django.http import HttpResponse, JsonResponse
from rest_framework.views import APIView
from rest_framework.response import Response
#from rest_framework.parsers import JSONParser
from django.contrib.auth import authenticate
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import SAFE_METHODS, BasePermission,IsAuthenticatedOrReadOnly,IsAuthenticated, IsAdminUser, DjangoModelPermissionsOrAnonReadOnly, DjangoModelPermissions
from myapp.renderers import UserRenderer
from rest_framework import status
from rest_framework import permissions
from rest_framework import generics
from myapp.models import Airport, Flight, User, Passenger, Booking
from myapp.serializers import *
from myapp.permissions import IsOwnerOrAdmin
from rest_framework import viewsets



def get_tokens_for_user(user):
  refresh = RefreshToken.for_user(user)
  return {
      'refresh': str(refresh),
      'access': str(refresh.access_token),
  }



# Create your views here.

class UserRegistrationView(APIView):
  renderer_classes = [UserRenderer]
  def post(self, request, format=None):
    serializer = UserRegistrationSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = serializer.save()
    token = get_tokens_for_user(user)
    return Response({'token':token, 'msg':'Registration Successful'}, status=status.HTTP_201_CREATED)

class UserLoginView(APIView):
  renderer_classes = [UserRenderer]
  def post(self, request, format=None):
    serializer = UserLoginSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    email = serializer.data.get('email')
    password = serializer.data.get('password')
    user = authenticate(email=email, password=password)
    if user is not None:
      token = get_tokens_for_user(user)
      return Response({'token':token, 'msg':'Login Success'}, status=status.HTTP_200_OK)
    else:
      return Response({'errors':{'non_field_errors':['Email or Password is not Valid']}}, status=status.HTTP_404_NOT_FOUND)


class UserProfileView(APIView):
  renderer_classes = [UserRenderer]
  permission_classes = [IsAuthenticated]
  def get(self, request, format=None):
    serializer = UserSerializer(request.user)
    return Response(serializer.data, status=status.HTTP_200_OK)


class UserListCreateAPIView(generics.ListCreateAPIView):
    permission_classes = [IsUserOrIsAdmin]
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsUserOrIsAdmin]
    queryset = User.objects.all()
    
    serializer_class = UserSerializer

    

class FlightListCreateAPIView(generics.ListCreateAPIView):
    permission_classes = [IsAdminUser | IsAuthenticatedOrReadOnly]
    queryset = Flight.objects.all()
    serializer_class = FlightSerializer
    
    


class FlightRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsAdminUser] 
    queryset = Flight.objects.all()
    serializer_class = FlightSerializer

class AirportListCreateAPIView(generics.ListCreateAPIView):
    permission_classes = [IsAdminUser | IsAuthenticatedOrReadOnly]
    queryset = Airport.objects.all()
    serializer_class = AirportSerializer

class AirportRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes  = [IsAdminUser]
    queryset = Airport.objects.all()
    serializer_class = AirportSerializer





class PassengerListCreateAPIView(generics.ListCreateAPIView):
    permission_classes = [IsUserOrIsAdminPassenger]
    queryset = Passenger.objects.all()
    serializer_class = PassengerSerializer

class PassengerRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsUserOrIsAdminPassenger]
    queryset = Passenger.objects.all()
    serializer_class = PassengerSerializer



class BookingRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [IsUserOrIsAdmin]
    # queryset = Booking.objects.all()
    # serializer_class = BookingSerializer
    def get_queryset(self):

        if self.request.user.is_staff == False:

            user_data= self.request.user
            book = Booking.objects.filter(user= user_data)
            return book
        else:
            book = Booking.objects.all()
            return book

    serializer_class = BookingSerializer

    
    
class BookViewSet(viewsets.ModelViewSet):
    permission_classes = [IsUserOrIsAdmin]
    # queryset = Book.objects.all()
    serializer_class = BookingSerializer
    # print(serializer_class)
    def get_queryset(self):

        if self.request.user.is_staff == False:

            user_data= self.request.user
            book = Booking.objects.filter(user= user_data)
            return book
        else:
            book = Booking.objects.all()
            return book
        

        # book = Booking.objects.all()
         

    def create(self, request, *args, **kwargs):
        data = request.data

        user = User.objects.get(id= request.user.pk)
        # user = User.objects.get(id=data["user"])
        flightdetails = Flight.objects.get(id=data["flights"])
        # bookingdetails = Booking.objects.get(no_of_passengers=data["no_of_passengers"])

        
        new_book = Booking.objects.create(
            booking_number= data["booking_number"],
            no_of_passengers= data["no_of_passengers"],
            user=user,
            flights=flightdetails,
        )
        new_book.save()
        for passenger in data["passenger"]:
            passenger_book= Passenger.objects.create(
                user = user,
                name= passenger["name"],
                contact_number = passenger["contact_number"],
                email = passenger["email"],
                gender = passenger["gender"],
                age = passenger["age"]

            )
            new_book.passenger.add(passenger_book)

            if flightdetails.available_seats < len(data["passenger"]):
                return Response({"data": "No seats available", "status": status.HTTP_400_BAD_REQUEST})
            update_seats = flightdetails.available_seats - data["no_of_passengers"]
            flightdetails.available_seats = update_seats
            flightdetails.save()
            serializers = BookingSerializer(new_book)
            return Response({"data": serializers.data, "status": status.HTTP_201_CREATED})






#urls.py

from django.urls import path, include
from myapp.views import *
from rest_framework import routers





router = routers.DefaultRouter()
router.register('booking', BookViewSet, basename="MyModel")
urlpatterns = [

    path('register/', UserRegistrationView.as_view(), name="register"),
    path('login/', UserLoginView.as_view(), name="login"),
    path('profile/', UserProfileView.as_view(), name="profile"),
    path('flight/', FlightListCreateAPIView.as_view()),
    path('flight_info/<int:pk>/', FlightRetrtieveUpdateDestroyAPIView.as_view()),
    path('customer/', UserListCreateAPIView.as_view()),
    path('customer_info/<int:pk>/', UserRetrtieveUpdateDestroyAPIView.as_view()),
    path('passenger/', PassengerListCreateAPIView.as_view()),
    path('passenger_info/<int:pk>/', PassengerRetrtieveUpdateDestroyAPIView.as_view()),
    
    path('booking_info/<int:pk>/', BookingRetrtieveUpdateDestroyAPIView.as_view()),
    #path('booking/', BookingAPIView.as_view()),
    path('', include(router.urls)),
    

    
    
    
]


Leave a Comment