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.

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 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:
# 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.
# 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.
# 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 responseDecorator @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 vì nó thể hiện sự hiểu biết về middleware, logging, và debug hệ thống production.
# 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:
# 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 TrueCấu hình filter trong settings.py:
# 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",
},
}Sẵn sàng chinh phục phỏng vấn Django?
Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.
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
# 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 NoneMẫu này cho phép decorate views với các yêu cầu permission:
# 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
passprocess_exception Cho Error Handling Tập Trung
# 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 NoneCá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, 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:
# 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ế.
# 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.
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.
Bắt đầu luyện tập!
Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.
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 = Truecho 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_exceptioncho 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àngdjango.utils.deprecation.MiddlewareMixindeprecated sẽ chuyển sangdjango.middleware.MiddlewareMixintrong 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.
Bạn có tìm ra lỗi trong Django không?
Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Viết bởi
Anthony Fillion-MailletNgười sáng lập SharpSkill
Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.
Cập nhật ngày 18 tháng 9, 2026
Thẻ
Chia sẻ
Bài viết liên quan

Django 5.2: Middleware Tùy Chỉnh và Xử Lý Signal trong Phỏng Vấn Kỹ Thuật Python
Hướng dẫn chi tiết về custom middleware và signal handling trong Django 5.2 cho phỏng vấn kỹ thuật. Bao gồm request pipeline, async middleware, post_save, pre_save và custom signals với mã mẫu thực tế.

Câu hỏi phỏng vấn Django: ORM, Middleware và DRF chi tiết
Câu hỏi phỏng vấn Django bao gồm tối ưu hóa ORM với select_related, prefetch_related và chế độ FETCH_PEERS của Django 6.1, kiến trúc middleware, hiệu suất serializer Django REST Framework, permissions và các pattern pagination.

Django 6.0 năm 2026: Composite Primary Key, Background Task và Câu hỏi phỏng vấn
Hướng dẫn toàn diện về Django 6.0 bao gồm composite primary key, framework background task tích hợp, template partial, CSP middleware cùng ví dụ code thực tế và chuẩn bị phỏng vấn.