Cả 4 đều giảm lượng dữ liệu kéo về từ DB, dùng khi không cần object đầy đủ.
.values('id', 'name') trả về QuerySet của dict chỉ chứa field liệt kê — không khởi tạo model instance nên nhanh và tiết kiệm RAM. .values_list('id', 'name') giống vậy nhưng trả tuple; thêm flat=True cho một field duy nhất: Post.objects.values_list('id', flat=True) → [1, 2, 3]. .only('title', 'slug') vẫn trả về model instance đầy đủ nhưng chỉ load field liệt kê — các field khác lazy-load khi access (mỗi access là 1 query thêm). .defer('body') ngược lại .only(): load mọi field trừ field defer — hợp khi có một field rất to (TextField, JSONField) ít khi cần dùng.
# List dropdown — chỉ cần id+title, không cần object
titles = Post.objects.values_list('id', 'title') # [(1, 'A'), (2, 'B')]
titles = Post.objects.values('id', 'title') # [{'id': 1, ...}, ...]
# Trang list, body rất nặng chỉ cần ở trang detail
posts = Post.objects.defer('body').all() # instance, body lazy.only() và .defer() vẫn trả instance nên có thể trigger N+1 nếu vô tình access field bị defer trong loop.
Còn .values() / .values_list() không có method của model (như get_absolute_url(), __str__()) — chỉ dùng khi không cần logic instance.
All four reduce the data pulled from the DB, used when you do not need the full object:
.values('id', 'name')— returns aQuerySetof dicts, only the listed fields. No model instance is constructed → fast, lean on RAM..values_list('id', 'name')— like.values()but returns tuples. Addflat=Truefor a single field:Post.objects.values_list('id', flat=True)→[1, 2, 3]..only('title', 'slug')— still returns full model instances, but only loads the listed fields; the rest lazy-load on access (each access = one extra query)..defer('body')— the opposite of.only(): loads every field except the deferred ones. Useful when a single field is very large (TextField,JSONField) and rarely needed.
# Dropdown — id+title only, no object needed
titles = Post.objects.values_list('id', 'title') # [(1, 'A'), (2, 'B')]
titles = Post.objects.values('id', 'title') # [{'id': 1, ...}, ...]
# List view; heavy body only needed on detail page
posts = Post.objects.defer('body').all() # instances, body lazyPitfall: .only() and .defer() still return instances so they can trigger N+1 if you accidentally access a deferred field in a loop. .values()/.values_list() have no model methods (e.g. get_absolute_url(), __str__()) — only use them when you do not need instance logic.