Trả lời nhanh: Django 6.2 sẽ nhận diện HTTP QUERY, một phương thức an toàn và lũy đẳng (idempotent) cho các truy vấn chỉ đọc, gửi tiêu chí tìm kiếm trong phần thân (body) của yêu cầu thay vì chuỗi truy vấn trên URL. Phiên bản 6.2 dự kiến ra mắt vào tháng 4 năm 2027, là bản LTS với các bản vá bảo mật trong ít nhất ba năm. Tính năng này vẫn đang được phát triển, vì vậy bạn chỉ nên thử trong môi trường phát triển, chưa dùng cho production.

Các API tìm kiếm có hàng chục bộ lọc thường rất khó xử lý: GET cho ra những URL dài ngoằng, còn POST thì sai về mặt ngữ nghĩa vì nó dùng để thay đổi dữ liệu. QUERY lấp đầy khoảng trống này: nó đọc dữ liệu như GET, nhưng mang tiêu chí phức tạp trong body như POST.

Vì sao GET và POST đều “lệch” với tìm kiếm phức tạp

GET phù hợp với các bộ lọc đơn giản, nhưng khi tiêu chí trở nên lồng nhau — danh sách tác giả, khoảng giá, các điều kiện kết hợp — việc mã hóa chúng vào chuỗi truy vấn nhanh chóng trở nên rối rắm và khó kiểm chứng (validate).

POST thì mang được dữ liệu phức tạp, nhưng các proxy và bộ nhớ đệm (cache) lại coi nó như một thao tác ghi, chứ không phải một thao tác đọc. Vì vậy, dùng POST cho tìm kiếm là một cách “lách” về ngữ nghĩa, dù về kỹ thuật vẫn chạy được.

QUERY hoạt động thế nào trong Django 6.2

Theo ghi chú phát hành Django 6.2 đang được phát triển, QUERY được coi là phương thức an toàn (safe): nó được miễn CSRF, được chấp nhận bởi require_safe(), và hỗ trợ xử lý có điều kiện qua ConditionalGetMiddleware cùng hàm condition() với ETag và phản hồi 304.

Trong class-based view, bạn định nghĩa phương thức query(), vì View.http_method_names nay đã bao gồm “query”. Tiêu chí tìm kiếm nằm trong request.body và phải được phân tích (parse) theo Content-Type — Django không tự đưa chúng vào request.POST.

import json
from django.http import JsonResponse
from django.views import View
from .models import Book
class BookSearchView(View):
def query(self, request):
data = json.loads(request.body)
authors = data.get("authors", [])[:100]
books = Book.objects.filter(author__name__in=authors)
return JsonResponse({"titles": [book.title for book in books]})

Để kiểm thử, Django bổ sung Client.query() mới, và phương thức này cũng có trên AsyncClient và RequestFactory.

Những giới hạn cần nhớ

  • QUERY không được bộ nhớ đệm bởi UpdateCacheMiddleware, FetchFromCacheMiddleware hay cache_page(), dù ETag vẫn hoạt động.
  • Khi bật DEBUG và APPEND_SLASH, CommonMiddleware sẽ raise RuntimeError cho yêu cầu QUERY tới một URL thiếu dấu gạch chéo cuối, giống như với DELETE, POST, PUT và PATCH.
  • Để giữ hành vi cũ chỉ cho phép GET và HEAD, hãy dùng require_http_methods(["GET", "HEAD"]) thay vì require_safe().

Lưu ý thực tế: QUERY còn rất mới, nên không phải mọi proxy, CDN hay client đều hỗ trợ nó. Hãy kiểm tra hạ tầng của bạn có chuyển tiếp QUERY nguyên vẹn hay không trước khi áp dụng.

Điều này có ý nghĩa gì với bạn

Với các API nội bộ hoặc API mà bạn kiểm soát cả client lẫn server, QUERY rất đáng thử khi Django 6.2 ra mắt: ngữ nghĩa rõ ràng hơn, việc kiểm chứng JSON trở nên dễ dàng, và bạn không còn phải dùng POST như một cách lách cho các thao tác đọc.

Với các API công khai, hãy chờ hệ sinh thái bắt kịp. Trong lúc đó, bạn vẫn có thể tách logic tìm kiếm thành một hàm riêng để sau này chuyển sang QUERY một cách dễ dàng.

Bài viết liên quan

Câu hỏi thường gặp

QUERY khác GET ở điểm nào?

GET đặt tiêu chí trong URL, còn QUERY đặt tiêu chí trong body. Nhờ đó, QUERY xử lý được các tiêu chí phức tạp trong khi vẫn giữ bản chất chỉ đọc.

QUERY khác POST ở điểm nào?

POST tạo ra hoặc thay đổi dữ liệu, còn QUERY an toàn và lũy đẳng, chỉ đọc dữ liệu — gọi lại nhiều lần vẫn cho cùng một kết quả.

Có nên dùng QUERY trên production ngay bây giờ không?

Chưa nên. Django 6.2 vẫn đang được phát triển và dự kiến ra mắt vào tháng 4 năm 2027. Hãy thử trong môi trường phát triển và kiểm tra xem proxy, CDN và client của bạn có hỗ trợ QUERY hay không.

💬 Tin này ảnh hưởng tới dự án của bạn thế nào? Chia sẻ góc nhìn của bạn trong phần bình luận — mình đọc hết và sẽ tổng hợp những ý hay nhất.

Nguồn tham khảo