Middleware в Django - это фреймворк для обработки запросов и ответов глобально для всего приложения. Это позволяет выполнять определенные действия до или после обработки запроса views-функциями.
- Обработка запросов до того, как они достигнут view
- Обработка ответов после того, как view сформировал их
- Обработка исключений
- Модификация request/response объектов
- Прерывание цепочки обработки запроса
Самый простой тип middleware - функция-обертка:
def simple_middleware(get_response):
def middleware(request):
# Код, выполняемый для каждого запроса до view
response = get_response(request)
# Код, выполняемый для каждого запроса/ответа после view
return response
return middleware
Более гибкий подход с использованием классов:
class ClassMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Предварительная обработка
response = self.get_response(request)
# Постобработка
return response
def process_view(self, request, view_func, view_args, view_kwargs):
# Выполняется непосредственно перед вызовом view
return None
def process_exception(self, request, exception):
# Обработка исключений
return None
def process_template_response(self, request, response):
# Обработка template response
return response
Middleware в Django выполняются в следующем порядке:
- request проходит через middleware сверху вниз (как указано в MIDDLEWARE settings)
- Достигает view
- response проходит через middleware снизу вверх
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
from django.core.exceptions import PermissionDenied
from django.core.cache import cache
class ThrottlingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.rate_limit = 100 # запросов
self.time_window = 3600 # секунд (1 час)
def __call__(self, request):
ip = request.META.get('REMOTE_ADDR')
key = f'throttle_{ip}'
requests = cache.get(key, 0)
if requests >= self.rate_limit:
raise PermissionDenied('Too many requests')
cache.set(key, requests + 1, self.time_window)
return self.get_response(request)
import logging
import time
class RequestLogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.logger = logging.getLogger(__name__)
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
execution_time = time.time() - start_time
self.logger.info(
f'Path: {request.path} Method: {request.method} '
f'Time: {execution_time:.2f}s Status: {response.status_code}'
)
return response
- Каждый middleware должен выполнять только одну конкретную задачу
- Не перегружайте middleware лишней логикой
- Используйте кэширование где это возможно
- Избегайте тяжелых операций в middleware
- Помните, что middleware выполняется для каждого запроса
- Всегда обрабатывайте возможные исключения
- Используйте process_exception для глобальной обработки ошибок
- Выносите настройки в settings.py
- Используйте переменные окружения для конфигурации
from django.conf import settings
class ConfigurableMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.enabled = getattr(settings, 'MIDDLEWARE_ENABLED', True)
self.timeout = getattr(settings, 'MIDDLEWARE_TIMEOUT', 30)
- Пишите unit-тесты для middleware
- Тестируйте различные сценарии выполнения
from django.test import TestCase, RequestFactory
class MiddlewareTestCase(TestCase):
def setUp(self):
self.factory = RequestFactory()
def test_middleware(self):
request = self.factory.get('/')
middleware = YourMiddleware(lambda r: None)
response = middleware(request)
self.assertIsNotNone(response)
- Отображает информацию о выполнении middleware
- Помогает отслеживать производительность
- Предоставляет дополнительные инструменты для разработки
- Включает полезные команды управления
import cProfile
class ProfilingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
profiler = cProfile.Profile()
response = profiler.runcall(self.get_response, request)
profiler.print_stats()
return response
Middleware - мощный инструмент Django для глобальной обработки запросов. При правильном использовании он позволяет:
- Улучшить безопасность приложения
- Оптимизировать производительность
- Добавить глобальную функциональность
- Централизовать общую логику
Помните о производительности и следуйте принципам чистого кода при разработке middleware.