Как пометить действие DRF ViewSet как освобожденное от применения пользовательского промежуточного ПО?
Я создал Custom Django Middleware и добавил в MIDDLEWARE
переменную настроек правильно.
from django.http import HttpResponseForbidden
class MyCustomMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
# Perform some internal actions on the `request` object.
return None
Поскольку по умолчанию это применяется ко всем DRF ViewSets, я хотел бы исключить некоторые действия, которые не нуждаются в этой проверке. Идея состоит в том, чтобы проверять флаг внутри функции process_view
, вдохновляясь функцией Django CsrfViewMiddleware
, которая проверяет, была ли переменная csrf_exempt
установлена декоратором csrf_exempt
. Поэтому я модифицировал пользовательское промежуточное ПО и создал пользовательский декоратор для явного освобождения представлений.
from functools import wraps
from django.http import HttpResponseForbidden
class MyCustomMiddleware:
...
def process_view(self, request, view_func, view_args, view_kwargs):
if getattr(view_func, "some_condition", False):
return HttpResponseForbidden("Forbidden on custom middleware")
# Perform some internal actions on the `request` object.
return None
def custom_middleware_exempt(view_func):
@wraps(view_func)
def _view_wrapper(request, *args, **kwargs):
return view_func(request, *args, **kwargs)
_view_wrapper.some_condition = True
return _view_wrapper
После этого я делаю что-то вроде этого, и оно корректно входит в пользовательский декоратор, прежде чем попасть в промежуточное ПО Django.
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
class MyViewSet(viewsets.ViewSet):
@action(detail=False, methods=['get'])
@custom_middleware_exempt
def my_action(self, request):
return Response()
Все было хорошо, пока я не заметил, что view_func
пользовательского промежуточного ПО process_view
соответствует не функции действия (которая декорируется), а функции ViewSet.
Внутри декоратора: view_func = <function MyViewSet.my_action at 0x79ee9c471760>
Внутри промежуточного программного обеспечения: view_func = <function MyViewSet at 0x79ee9c49c220>
По-видимому, промежуточные модули Django применяются на уровне наборов представлений, а не на уровне действий. Как следствие, view_func
не имеет установленного атрибута some_condition
.
Есть ли способ украсить действие набора видов и изменить функцию уровня набора видов или альтернативный способ достичь того, что я пытаюсь сделать?
Внутри вашего промежуточного ПО вы можете просто проверить наличие флага в объекте запроса, а не непосредственно в функции представления, и на основании этого флага освободить действие.
Так что в вашем MyCustomMiddleware
вы можете проверить объект запроса следующим образом:
def process_view(self, request, view_func, view_args, view_kwargs):
if getattr(request, "custom_middleware_exempt", False):
return None # Skip middleware
# whatever you want to do here
return None
Это должно автоматически освободить вас от действий, украшенных символами @custom_middleware_exempt