Как добавить разрешения для "class UserRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView)"?
Я создал модель, используя абстрактный класс модели пользователя, для онлайн бронирования авиабилетов. Я новичок в этом деле, поэтому не добавил в нее много функциональных возможностей. Я делюсь своими model.py, admin.py, serializer.py, view.py.
Мой вопрос:
- В views.py -> "class UserRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView)"
Я хочу предоставить доступ для GET PUT DELETE только ADMIN и USER, который создал этот профиль (владелец). Я использую postman для проверки конечных точек.
"Пожалуйста, проверьте мою абстрактную модель пользователя, если есть какие-то ошибки".
- разрешение для "BookViewSet" и "BookingRetrtieveUpdateDestroyAPIView" Я хочу, чтобы только ADMIN и USER владелец, который создал это бронирование, могли просматривать или изменять его.
Соответствующий сериализатор
#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__'
#admin.py
from django.contrib import admin
from .models import Airport, Booking, Flight, User, Passenger
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class UserModelAdmin(BaseUserAdmin):
# The fields to be used in displaying the User model.staff= models.BooleanField(default=False)
# These override the definitions on the base UserModelAdmin
# that reference specific fields on auth.User.
list_display = ('id', 'email', 'name', 'is_admin','is_active')
list_filter = ('is_admin',)
fieldsets = (
('User Credentials', {'fields': ('email', 'password')}),
('Personal info', {'fields': ('name', 'contact_number', 'gender', 'dob','address', 'state', 'city', 'country', 'pincode',)}),
('Permissions', {'fields': ('is_admin',)}),
)
# add_fieldsets is not a standard ModelAdmin attribute. UserModelAdmin
# overrides get_fieldsets to use this attribute when creating a user.
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'name', 'password1', 'password2',),
}),
)
search_fields = ('email',)
ordering = ('email', 'id')
filter_horizontal = ()
# Register your models here.
admin.site.register(User,UserModelAdmin)
admin.site.register([Airport,Flight,Passenger,Booking])
#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)),
]
Для этого вам нужно будет создать пользовательское разрешение . Поскольку разрешение зависит от экземпляра User
, вы захотите реализовать has_object_permission()
, возвращающий True, если пользователь is_staff
или если пользователь такой же, как User
, к которому пытаются получить доступ:
from django.contrib.auth import get_user_model
from rest_framework.permissions import BasePermission
User = get_user_model()
class IsUserOrIsAdmin(BasePermission):
"""Allow access to the respective User object and to admin users."""
def has_object_permission(self, request, view, obj):
return (request.user and request.user.is_staff) or (
isinstance(obj, User) and request.user == obj
)
Затем вы можете установить permission_classes вашего представления на ваше пользовательское разрешение:
class UserRetrtieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [IsUserOrIsAdmin]
queryset = User.objects.all()
serializer_class = UserSerializer