Dùng đối tượng Prefetch để chỉ định QuerySet con, thay vì chuỗi string.
prefetch_related('comments') luôn kéo toàn bộ comment. Nếu chỉ cần comment đã duyệt, sắp mới nhất trước:
from django.db.models import Prefetch
approved = Comment.objects.filter(is_approved=True).order_by('-created_at')
posts = Post.objects.prefetch_related(
Prefetch('comments', queryset=approved, to_attr='approved_comments')
)
for post in posts:
post.approved_comments # a plain Python list, no extra queryBa tham số cần biết:
- lookup — tên quan hệ, hỗ trợ đi sâu ('comments__author').
- queryset — QuerySet con, có thể kèm select_related để gộp luôn author của comment.
- to_attr — gắn kết quả vào một attribute mới dạng list. Không có to_attr thì kết quả ghi đè cache của related manager, và mọi lần gọi post.comments.all() sau đó đều trả về bản đã lọc — dễ gây hiểu nhầm.
Cạm bẫy: gọi .filter() trên related manager sau khi đã prefetch (post.comments.filter(...)) sẽ bỏ qua cache và bắn query mới cho từng dòng, tức là quay lại N+1.