Cả 3 đều là response object, chọn cái nào tuỳ vào kiểu dữ liệu và kích thước.
HttpResponse(content, content_type=...) buffer toàn bộ body trong RAM rồi trả — hợp với HTML, text, binary nhỏ. JsonResponse({...}) là wrapper quanh HttpResponse với content_type='application/json' cộng json.dumps — hợp với API trả dict; nếu trả list phải set safe=False. StreamingHttpResponse(generator) không buffer mà stream từng chunk — hợp với CSV export, file lớn, server-sent events.
from django.http import StreamingHttpResponse
import csv
def export_csv(request):
def rows():
yield ['id', 'title']
for p in Post.objects.iterator(chunk_size=2000):
yield [p.id, p.title]
pseudo = (','.join(map(str, r)) + '\n' for r in rows())
response = StreamingHttpResponse(pseudo, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="posts.csv"'
return responseHai chỗ dễ vấp: streaming response không nén được qua middleware GZip (Django giữ chunked transfer), nên phải nén ở nginx hoặc gửi file đã nén sẵn.
Còn JsonResponse mặc định escape Unicode — set json_dumps_params={'ensure_ascii': False} để giữ UTF-8 đọc được.