# Django Middleware Nâng Cao 2026: Custom Middleware, Logging và Câu Hỏi Phỏng Vấn > Hướng dẫn toàn diện về Django middleware năm 2026 bao gồm cách tạo custom middleware, triển khai logging hiệu quả, và các câu hỏi phỏng vấn thường gặp dành cho lập trình viên Django cấp cao. - Published: 2026-09-18 - Updated: 2026-09-18 - Author: Anthony Fillion-Maillet - Tags: django, middleware, python, logging, interview - Reading time: 12 min --- Django middleware nằm ở trung tâm của mọi chu trình request-response, tuy nhiên nhiều lập trình viên vẫn coi nó như một hộp đen. Hiểu rõ cách middleware thực thi, khi nào nên viết custom middleware, và cách triển khai logging ở tầng middleware là điều phân biệt giữa lập trình viên Django senior và junior trong các cuộc phỏng vấn kỹ thuật. > **Django 6.0 Middleware** > > Django 6.0 hỗ trợ đầy đủ async middleware với cú pháp async/await native. Thiết lập `async_capable = True` và `sync_capable = False` trên middleware class để xử lý request mà không có overhead từ thread. ## Cách Django Middleware Thực Thi Trong Chu Trình Request-Response Middleware trong Django tuân theo mô hình "onion" (củ hành). Khi request đến, nó đi qua từng middleware trong `MIDDLEWARE` từ trên xuống dưới. Khi view trả về response, response đi ngược lại qua middleware từ dưới lên trên. Thứ tự này rất quan trọng: middleware cần dữ liệu session phải chạy sau `SessionMiddleware`. Cấu hình `MIDDLEWARE` mặc định trong Django 6.0: ```python # settings.py MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ] ``` Mỗi middleware có thể cắt ngắn chuỗi bằng cách trả về `HttpResponse` trực tiếp thay vì gọi `get_response()`. Khi điều này xảy ra, middleware bên trong và view không bao giờ được thực thi, nhưng middleware bên ngoài vẫn xử lý response. ## Viết Custom Middleware Dựa Trên Class Trong Django 6.0 Mẫu middleware hiện đại yêu cầu một class với các method `__init__` và `__call__`. Method `__init__` chạy một lần khi server khởi động, trong khi `__call__` chạy cho mỗi request. ```python # middleware/timing.py import time import logging logger = logging.getLogger(__name__) class RequestTimingMiddleware: """Ghi lại thời gian xử lý mỗi request.""" def __init__(self, get_response): # Được gọi một lần khi server khởi động self.get_response = get_response def __call__(self, request): # Code trước khi view thực thi start_time = time.perf_counter() # Gọi middleware tiếp theo hoặc view response = self.get_response(request) # Code sau khi view thực thi duration_ms = (time.perf_counter() - start_time) * 1000 logger.info( "Request %s %s hoàn thành trong %.2fms", request.method, request.path, duration_ms ) return response ``` Đăng ký middleware trong `settings.py` bằng cách thêm import path vào `MIDDLEWARE`. Vị trí rất quan trọng: đặt timing middleware ở đầu danh sách để đo toàn bộ vòng đời request. ## Async Middleware Cho Ứng Dụng Django High-Concurrency Django 6.0 xử lý async request một cách native. Đối với ứng dụng chạy dưới ASGI với async views, sync middleware tạo ra bottleneck hiệu năng vì Django bọc sync middleware trong thread pool executors. Viết async middleware loại bỏ overhead này. ```python # middleware/async_timing.py import time import logging from asgiref.sync import iscoroutinefunction, markcoroutinefunction logger = logging.getLogger(__name__) class AsyncRequestTimingMiddleware: """Async-native timing middleware cho deployment ASGI.""" async_capable = True sync_capable = False def __init__(self, get_response): self.get_response = get_response if iscoroutinefunction(self.get_response): markcoroutinefunction(self) async def __call__(self, request): start_time = time.perf_counter() # Await middleware tiếp theo hoặc async view response = await self.get_response(request) duration_ms = (time.perf_counter() - start_time) * 1000 logger.info( "Async request %s %s hoàn thành trong %.2fms", request.method, request.path, duration_ms ) return response ``` Decorator `@sync_and_async_middleware` từ `django.utils.decorators` tạo middleware xử lý cả request sync và async bằng cách kiểm tra `iscoroutinefunction(get_response)` tại runtime. ## Triển Khai Request ID Logging Middleware Tương quan log trong hệ thống phân tán yêu cầu một identifier duy nhất cho mỗi request. Mẫu này thường xuất hiện trong [câu hỏi phỏng vấn Django](/technologies/django/interview-questions/django-middleware) vì nó thể hiện sự hiểu biết về middleware, logging, và debug hệ thống production. ```python # middleware/request_id.py import uuid import logging class RequestIDMiddleware: """Gắn request ID duy nhất vào mỗi request để tương quan log.""" def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # Tạo hoặc trích xuất request ID từ header request_id = request.headers.get("X-Request-ID") if not request_id: request_id = str(uuid.uuid4()) # Gắn vào object request để truy cập trong views request.request_id = request_id response = self.get_response(request) # Thêm request ID vào response headers response["X-Request-ID"] = request_id return response ``` Để bao gồm `request_id` trong tất cả các thông điệp log, tạo một logging filter tùy chỉnh: ```python # logging_filters.py import logging class RequestIDFilter(logging.Filter): """Chèn request_id vào log records.""" def filter(self, record): from django.middleware.request_id import local record.request_id = getattr(local, "request_id", "no-request-id") return True ``` Cấu hình filter trong `settings.py`: ```python # settings.py LOGGING = { "version": 1, "disable_existing_loggers": False, "filters": { "request_id": { "()": "logging_filters.RequestIDFilter", }, }, "formatters": { "verbose": { "format": "[{levelname}] {asctime} [{request_id}] {name}: {message}", "style": "{", }, }, "handlers": { "console": { "class": "logging.StreamHandler", "formatter": "verbose", "filters": ["request_id"], }, }, "root": { "handlers": ["console"], "level": "INFO", }, } ``` ## Hook Method Middleware Để Kiểm Soát Chi Tiết Ngoài `__call__`, Django middleware hỗ trợ ba hook method: `process_view`, `process_exception`, và `process_template_response`. Các method này cung cấp khả năng kiểm soát tại các điểm cụ thể trong vòng đời request. ### process_view Cho Logic Pre-Execution ```python # middleware/permission_check.py from django.http import HttpResponseForbidden class PermissionCheckMiddleware: """Kiểm tra quyền trước khi thực thi view.""" 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): # Truy cập metadata của view required_permission = getattr(view_func, "required_permission", None) if required_permission: if not request.user.has_perm(required_permission): return HttpResponseForbidden("Permission denied") # Return None để tiếp tục đến view return None ``` Mẫu này cho phép decorate views với các yêu cầu permission: ```python # views.py def require_permission(perm): def decorator(view_func): view_func.required_permission = perm return view_func return decorator @require_permission("app.can_edit") def edit_resource(request, pk): # Logic view pass ``` ### process_exception Cho Error Handling Tập Trung ```python # middleware/error_tracking.py import logging import traceback logger = logging.getLogger(__name__) class ErrorTrackingMiddleware: """Ghi lại exception với đầy đủ ngữ cảnh trước khi Django xử lý.""" def __init__(self, get_response): self.get_response = get_response def __call__(self, request): return self.get_response(request) def process_exception(self, request, exception): logger.error( "Unhandled exception trong %s %s: %s\n%s", request.method, request.path, str(exception), traceback.format_exc(), extra={ "user_id": getattr(request.user, "id", None), "request_id": getattr(request, "request_id", None), } ) # Return None để Django xử lý exception return None ``` Các method `process_exception` của middleware thực thi theo thứ tự ngược lại. Nếu một middleware trả về `HttpResponse`, middleware ở trước trong stack sẽ không thấy exception. ## Cập Nhật Security Middleware Django 6.0 Django 6.0 đi kèm với một số bản vá bảo mật cho `UpdateCacheMiddleware`. Theo [Django security releases từ 2026](https://www.djangoproject.com/weblog/2026/jun/03/security-releases/), response với `Cache-Control: private` sử dụng mixed case bị cache sai, và response cho request có header `Authorization` có thể được lưu trong shared caches. LoginRequiredMiddleware, được giới thiệu trong Django 5.1, bắt buộc xác thực toàn site: ```python # settings.py MIDDLEWARE = [ # ... middleware khác "django.contrib.auth.middleware.LoginRequiredMiddleware", ] # Miễn trừ view cụ thể from django.contrib.auth.decorators import login_not_required @login_not_required def public_view(request): return HttpResponse("Nội dung công khai") ``` Điều này đảo ngược mẫu truyền thống decorate protected views với `@login_required`. Đối với ứng dụng mà hầu hết views yêu cầu xác thực, điều này giảm boilerplate và ngăn ngừa việc vô tình expose endpoint được bảo vệ. ## MiddlewareMixin và Migration Từ Legacy Middleware `MiddlewareMixin` kết nối middleware kiểu cũ (sử dụng method `process_request` và `process_response`) với mẫu callable mới. Lưu ý rằng `django.utils.deprecation.MiddlewareMixin` đã deprecated và sẽ bị xóa trong Django 6.2. Sử dụng `django.middleware.MiddlewareMixin` thay thế. ```python # middleware/legacy_style.py from django.middleware import MiddlewareMixin class LegacyStyleMiddleware(MiddlewareMixin): """Middleware sử dụng mẫu hook-based legacy.""" def process_request(self, request): # Được gọi trước view, return None để tiếp tục request.custom_attribute = "value" return None def process_response(self, request, response): # Được gọi sau view, phải return response response["X-Custom-Header"] = "middleware-added" return response ``` Đối với middleware mới, tránh `MiddlewareMixin`. Mẫu callable cung cấp luồng điều khiển rõ ràng hơn và tương thích tốt hơn với async Django. ## Câu Hỏi Phỏng Vấn Django Middleware Phổ Biến Các cuộc phỏng vấn kỹ thuật thường bao gồm câu hỏi về middleware để đánh giá sự hiểu biết về vòng đời request của Django. Những câu hỏi này thường xuất hiện trong [phỏng vấn lập trình viên Django senior](/blog/django/django-interview-orm-middleware-drf). **H: Sự khác biệt giữa thứ tự middleware và thứ tự thực thi cho response là gì?** Middleware xử lý request từ trên xuống dưới qua `MIDDLEWARE` nhưng xử lý response từ dưới lên trên. Hãy tưởng tượng như củ hành: middleware ngoài cùng là middleware đầu tiên thấy request và cuối cùng thấy response. **H: Middleware short-circuiting hoạt động như thế nào?** Khi middleware trả về `HttpResponse` thay vì gọi `get_response()`, request không bao giờ đến được middleware bên trong hoặc view. Response vẫn đi qua tất cả middleware bên ngoài trên đường về. Hành vi này khác với setting `MIDDLEWARE_CLASSES` legacy, nơi tất cả method `process_response` chạy bất kể short-circuiting. **H: Khi nào middleware nên truy cập `request.user`?** Chỉ sau khi `AuthenticationMiddleware` đã chạy. Truy cập `request.user` trước khi authentication middleware gắn nó sẽ gây ra `AttributeError`. Đặt custom middleware cần thông tin user sau `AuthenticationMiddleware` trong danh sách `MIDDLEWARE`. **H: Làm thế nào để middleware tương thích với async?** Thiết lập `async_capable = True` trên middleware class và triển khai `__call__` như một async method sử dụng `await get_response(request)`. Đối với middleware phải hoạt động trong cả ngữ cảnh sync và async, sử dụng `@sync_and_async_middleware` và kiểm tra `iscoroutinefunction(get_response)` để phân nhánh phù hợp. ## Thành Thạo Django Middleware Cho Production và Phỏng Vấn Django middleware kiểm soát các cross-cutting concerns bao trùm toàn bộ vòng đời request. Các điểm quan trọng khi làm việc với middleware trong Django 6.0: - Middleware thực thi theo mẫu onion: request chảy từ trên xuống, response chảy từ dưới lên - Thiết lập `async_capable = True` cho async-native middleware trong deployment ASGI để tránh overhead thread pool - Sử dụng `process_view` để kiểm tra metadata view trước khi thực thi, `process_exception` cho logging error tập trung - Request ID middleware cho phép tương quan log giữa các service phân tán, một yêu cầu phổ biến trong production - `LoginRequiredMiddleware` đảo ngược mẫu xác thực: views được bảo vệ theo mặc định, views công khai được miễn trừ rõ ràng - `django.utils.deprecation.MiddlewareMixin` deprecated sẽ chuyển sang `django.middleware.MiddlewareMixin` trong Django 6.2 - Thứ tự middleware quyết định component nào thấy `request.user`, dữ liệu session, và các thuộc tính request khác Để tìm hiểu sâu hơn về các mẫu Django ORM và REST framework, xem [hướng dẫn tối ưu Django ORM](/blog/django/django-orm-optimizing-queries). --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/vi/blog/django/django-advanced-middleware-logging-2026