Как применить промежуточное ПО Django везде, кроме единственного пути?
Я использую Python 3.9 с Django 3. Я определил это промежуточное ПО ...
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'directory.middleware.extend_token_response.ExtendTokenResponse'
]
Однако я не хочу, чтобы промежуточное ПО применялось к определенному URL. Я жестко закодировал это в промежуточном ПО так
class ExtendTokenResponse:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
response = self.get_response(request)
if request.path != '/' + LOGOUT_PATH:
# Code to be executed for each request before
# the view (and later middleware) are called.
is_expired = True
try:
token = request.auth
print("req path: %s" % request.path)
is_expired = is_token_expired(token) if token else True
except Exception as err:
print(err)
if not is_expired:
но это кажется немного небрежным, и я думаю, что промежуточное ПО поставляется с чем-то из коробки для настройки, что не нужно применять к моему пути "/logout". Есть ли более элегантный способ настроить это?
Django сам по себе не предоставляет решения для этого. Вероятно, жесткое кодирование/определение путей в настройках/среднем ПО - это нормально, пока это среднее ПО существует в первую очередь для одного конкретного проекта.
Однако, если вы хотите пометить определенные представления, чтобы исключить их из обработки, вы можете использовать декораторы так же, как это делает Django с декоратором csrf_exempt.
from functools import wraps
def token_response_exempt(view_func):
# Set an attribute on the function to mark it as exempt
def wrapped_view(*args, **kwargs):
return view_func(*args, **kwargs)
wrapped_view.token_response_exempt = True
return wraps(view_func)(wrapped_view)
# your middleware
class ExtendTokenResponse:
def process_view(request, view_func, view_args, view_kwargs):
if getattr(view_func, "token_response_exempt", False):
return None
# do your middleware stuff here...
# ....
А затем вы можете использовать декоратор, как показано ниже:
# urls.py
urlpatterns = [
path('logout/', token_response_exempt(LogOutView.as_view())),
]
По поводу вашего случая у меня есть 2 рекомендации:
Метод 1: использовать process_view и определить список func, которые будут исключены со структурой "app.module.func" и проверить пропустить в process_view
# In settings.py
EXCLUDE_FROM_MY_MIDDLEWARE =set({'custom_app.views.About'})
# In middlewares.py
class ExtendTokenResponse:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
logger.info(f'request hit request {request}')
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
def process_view(self, request, view_func, view_args, view_kwargs):
view_function = '.'.join((view_func.__module__, view_func.__name__))
exclusion_set=getattr(settings,'EXCLUDE_FROM_MY_MIDDLEWARE',set() )
if view_function in exclusion_set:
return None
Метод 2: Используйте decorator_from_middleware
и применяйте промежуточное ПО к каждой функции, нуждающейся в нем.
from django.utils.decorators import decorator_from_middleware
# with function view
@decorator_from_middleware(ExtendTokenResponse)
def view_function(request):
...
#with class view
class SimpleMiddlewareMixin:
@decorator_from_middleware(ExtendTokenResponse)
def dispatch(*args, **kwargs):
return super().dispatch(*args, **kwargs)
class MyClassBasedView(SimpleMiddlewareMixin, ListView):