render(), redirect(), HttpResponse, JsonResponse
corebeginnerrender(request, template, context) builds an HttpResponse from a template; redirect(to) builds a 302 to a URL, view name, or model; HttpResponse(content) wraps raw content directly; JsonResponse(data) serializes a dict to JSON with the right content type.
Think of it as
These four are just different factories for the one thing every view must produce — an HttpResponse. render() asks a template to do the work, redirect() asks the browser to go somewhere else instead, HttpResponse hands back exactly the bytes given, and JsonResponse is HttpResponse pre-configured for one very common case: a dict, serialized, with the right Content-Type already set.
What we're doing: Return a JSON list from an API view, correctly opting out of JsonResponse's dict-only default.
- 5
- safe=False is required here because titles is a list, not a dict — JsonResponse refuses to serialize anything but a dict unless told explicitly.
Why this works: JsonResponse defaults to safe=True as a security measure: serializing a top-level JSON array was historically exploitable in old browsers via a redefined Array constructor. Requiring safe=False to opt out makes serializing a non-dict a deliberate choice, not an accident.
Passing a list to JsonResponse without safe=False
Wrong
Better
What you see: TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.
Why: JsonResponse's safe=True default only accepts a dict — Django raises immediately rather than silently serializing a list, forcing safe=False to be an explicit, deliberate choice at every call site that needs it.
- render(): same page, HTML — template → HttpResponse
- HttpResponse(): same page, between HTML and data — raw content, any content_type
- redirect(): somewhere else / raw data, HTML — 302 to a URL, view name, or model
- JsonResponse(): somewhere else / raw data, data — dict → JSON, safe=False for a list
Response helpers at a glance
Together
Remember: render() builds a template response, redirect() builds a 302 (to a URL, view name, or model), JsonResponse defaults to dict-only unless given safe=False.
See also: views · templates · reverse and reverse lazy

