#python #django #django-rest-framework
#python #django #django-rest-framework
Вопрос:
Я создаю конечные точки с использованием DRF (Django Rest Framework).
django==2.1.5
djangorestframework==3.9.1
django-rest-auth
djangorestframework-jwt
У меня есть модель «Item», и я хочу установить разные классы разрешений для запросов GET и POST.
Вот как я это делаю:
@csrf_exempt
@api_view(['GET', 'POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([AllowAny])
def item_list(request):
if request.method == 'GET':
items = Item.objects.all()
serializer = ItemSerializer(items, many=True)
return JsonResponse(serializer.data, safe=False)
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = ItemSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)
Я хочу использовать одну конечную точку для всех методов, например, так:
urlpatterns = [
path('api/item/', views.item_list),
path('api/item/<int:pk>/', views.item_details),
]
Я хочу, чтобы AllowAny
пользователь для GET
метода запроса
и проверьте, есть ли isAdminUser
для POST
метода запроса
Могу ли я сделать это как в Flask, т. Е. Один декоратор для одного метода?
Ответ №1:
Поскольку вы используете представления на основе функций, нет возможности переопределять какие-либо методы. Что вы можете сделать сейчас, это создать новый класс разрешений и включить в него свою логику
# permissions.py
from rest_framework.permissions import IsAdminUser
class MyCustomPermission(IsAdminUser):
def has_permission(self, request, view):
if request.method == 'GET':
return True
else:
return super().has_permission(request, view)
и используйте его, на ваш взгляд, как,
# views.py
@csrf_exempt
@api_view(['GET', 'POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([MyCustomPermission]) # chage is here
def item_list(request):
if request.method == 'GET':
items = Item.objects.all()
serializer = ItemSerializer(items, many=True)
return JsonResponse(serializer.data, safe=False)
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = ItemSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)
Если вы планируете перейти на представления на основе классов, вы могли бы сделать это, переопределив get_permissions()
метод.
Вы можете найти простой пример здесь
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
if self.request.method == 'GET':
permission_classes = [AllowAny]
else:
permission_classes = [IsAdminUser]
return [permission() for permission in permission_classes]
Ответ №2:
Используйте представления на основе классов, определяйте и используйте пользовательские разрешения
Ответ №3:
Вы могли бы рассмотреть возможность определения двух отдельных функций с разными классами разрешений для «get» и «post».
@api_view(['GET')
@permission_classes([AllowAny])
def item_list_get(request):
if request.method == 'GET':
items = Item.objects.all()
serializer = ItemSerializer(items, many=True)
return JsonResponse(serializer.data, safe=False)
@csrf_exempt
@api_view(['POST'])
@authentication_classes([TokenAuthentication])
@permission_classes([isAdminUser])
def item_list_post(request):
if request.method == 'POST':
data = JSONParser().parse(request)
serializer = ItemSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)