Requests, Responses, and Shortcuts
Django uses request and response objects to pass state through the system. When a page is requested, Django creates an HttpRequest object containing metadata about that request. It then loads the appropriate view and passes this object as the first argument to it. Each view is responsible for returning an HttpResponse object.
The HttpRequest Object
The HttpRequest object contains specific information about the current request. You can use its attributes to access data submitted by the user or to understand the context of the request.
Request Attributes
Here are the most commonly used attributes of HttpRequest:
| Attribute | Description |
|---|---|
scheme | A string representing the scheme of the request, usually http or https. |
body | The raw request body as a byte string. Useful for processing raw or non-form data like binary images or XML payloads. |
path | The full URL path requested by the client, excluding the domain and query string. Example: /music/bands/the_beatles/ |
path_info | The portion of the URL path used for routing. It remains consistent even if the application is hosted under a subpath. |
method | The HTTP method used in the request, such as GET or POST. |
GET | A dictionary-like object containing all query string parameters from the URL. These are available regardless of whether the request method is GET or POST. |
POST | A dictionary-like object containing form data submitted in a POST request, typically from an HTML form. It does not include query string parameters or uploaded files. |
FILES | A dictionary-like object containing uploaded files. Each key matches the name attribute of a file input, and each value is an UploadedFile object. Only populated when the form uses enctype="multipart/form-data". |
COOKIES | A dictionary containing all cookies sent by the client. |
META | A dictionary containing all available HTTP headers. |
headers | A case-insensitive mapping of HTTP-prefixed headers, plus CONTENT_LENGTH and CONTENT_TYPE. Inside templates, you can look up headers using underscores instead of hyphens (Ex: {{ request.headers.user_agent }}). |
user | The currently authenticated user object. If no user is logged in, this will be an anonymous user object. |
session | A dictionary-like object representing the current user session. You can read and store data here between requests. |
NOTE
It is possible that a request can come in via POST with an empty POST dictionary. This happens if a form is requested via the POST method but does not include form data. Therefore, you should not use if request.POST to check for use of the POST method. Instead, always use if request.method == "POST".
Request Methods
Here are most commonly used methods of HttpRequest:
| Method | Description |
|---|---|
get_full_path() | Returns the full path of the request, including the query string. Example: /search/?q=django. |
build_absolute_uri(location) | Returns an absolute URL including the scheme and domain. If location is provided, it builds a full URL for that location. |
get_host() | Returns the host (domain name and optional port) used in the request. Example: example.com or localhost:8000. |
get_port() | Returns the port number used for the request. |
is_secure() | Returns True if the request was made using HTTPS, otherwise False. |
get_signed_cookie(key) | Returns a cookie value for a signed cookie or raises an exception if the signature is invalid. |
auser() | Async version of user. A coroutine that returns the authenticated user in asynchronous views. |
For a complete list of HttpRequest attributes and methods, refer to this official doc.
QueryDict Objects
The request.GET and request.POST attributes are instances of django.http.QueryDict, a specialized dictionary-like class called QueryDict. It is designed to handle multiple values for the same key, which often happens in HTML forms (Ex: <select multiple>).
A QueryDict behaves much like a normal dictionary. However, it also supports multiple values per key.
Example:
If a user visits https://example.com/?tag=python&tag=django:
# Returns only the last value
request.GET['tag']
# Output: "django"
# Returns all values
request.GET.getlist('tag')
# Output: ["python", "django"]Key Features:
- Immutability: The
QueryDictinstances inrequest.GETandrequest.POSTare immutable. You cannot change them directly. If you need to modify the data, you must call.copy()first to get a mutable version. - Multiple Values: Unlike a standard Python dictionary, a
QueryDictcan store a list of values for a single key.
| Method | Description |
|---|---|
copy() | Returns a mutable copy of the QueryDict. |
__getitem__ (Ex: request.GET['key']) | Returns the last value for the given key. If the key has multiple values, only the last one is returned. Raises KeyError if the key is missing. |
get(key, default=None) | Returns the value for the given key if it exists, otherwise returns default. This is safer than using brackets [] because it avoids errors on missing keys. |
getlist(key) | Returns all values for the given key as a Python list. Use this when a form field sends multiple values. |
__contains__ (Ex: 'key' in request.GET) | Returns True if the given key is set, otherwise False. |
urlencode() | Returns a string of the data in query string format (Ex: name=john&age=25). |
For more info on QueryDict objects, refer to this official doc.
The HttpResponse Object
NOTE
The HttpResponseBase class is the parent of all Django response objects. It should not be used to create responses directly, but it can be useful for type-checking.
Unlike HttpRequest objects, which are created automatically by Django, HttpResponse objects are your responsibility. You must instantiate and return one in every view function. You can pass it a simple string, bytestring, memoryview, an iterator, an HTML template, or even binary data (Ex: images or files).
from django.http import HttpResponse
response = HttpResponse("Here is the text of the web page.")
response = HttpResponse("Text only, please.", content_type="text/plain")
response = HttpResponse(b"Bytestrings are also accepted.")
response = HttpResponse(memoryview(b"Memoryview as well."))Response Attributes
Here are most commonly used attributes of HttpResponse:
| Attribute | Description |
|---|---|
content | The content of the response as a bytestring. This is what will be sent to the browser. |
status_code | The HTTP status code (e.g., 200, 404). Changing this also updates the reason_phrase. |
reason_phrase | The HTTP reason phrase corresponding to the status code (e.g., "OK", "Not Found"). |
headers | A case-insensitive, dictionary-like object that provides access to all HTTP headers (except Set-Cookie). |
cookies | A dictionary containing the cookies included in the response. |
charset | A string denoting the encoding of the response (defaults to utf-8). |
closed | Returns True if the response has been closed. |
Response Methods
Here are most commonly used methods of HttpResponse:
| Method | Description |
|---|---|
__setitem__ | Sets a header value. Example: response['Age'] = 120. |
__delitem__ | Deletes a header. Example: del response['Age']. |
set_cookie() | Sets a cookie. Arguments include key, value, max_age, expires, path, domain, secure, and httponly. |
delete_cookie() | Removes a cookie from the response. |
write(content) | Appends content to the response body (file-like behavior). |
flush() | Flushes the response buffer. |
setdefault() | Sets a header only if it hasn't been set yet. |
HttpResponse Subclasses
Django provides built-in subclasses for common HTTP status codes. Using these is often more readable than setting status_code manually.
| Class Name | Status Code | Description |
|---|---|---|
HttpResponseRedirect | 302 | Temporary redirect. |
HttpResponsePermanentRedirect | 301 | Permanent redirect. |
HttpResponseNotModified | 304 | Indicates the page has not changed since the last request. |
HttpResponseBadRequest | 400 | Bad request syntax. |
HttpResponseForbidden | 403 | Permission denied. |
HttpResponseNotFound | 404 | Page not found. |
HttpResponseNotAllowed | 405 | Method not allowed (requires a list of permitted methods). |
HttpResponseServerError | 500 | Internal server error. |
Custom Subclasses
If you need a custom response class, you can inherit from HttpResponse and set the status_code attribute.
from http import HTTPStatus
from django.http import HttpResponse
class HttpResponseNoContent(HttpResponse):
status_code = HTTPStatus.NO_CONTENTJsonResponse Object
The JsonResponse class is a subclass of HttpResponse that helps you create JSON-encoded responses. It automatically sets the Content-Type header to application/json.
Key Parameters:
- data: The dictionary (or object) to serialize.
- safe: Defaults to
True. If you want to serialize a list or non-dict object, you must set this toFalse.
from django.http import JsonResponse
# Default: safe=True (only accepts dicts)
response = JsonResponse({'foo': 'bar'})
# safe=False (accepts lists and other types)
response = JsonResponse([1, 2, 3], safe=False)TemplateResponse Object
Standard HttpResponse objects are "static", i.e., once created, they hold the final, rendered content. TemplateResponse is different: it uses lazy rendering. Instead of generating the HTML immediately, it stores the template and context data and waits to render them until the last possible moment (usually just before the response is sent to the client). This allows middleware to modify the context.
from django.template.response import TemplateResponse
def my_view(request):
# The HTML is NOT generated yet!
response = TemplateResponse(request, 'myapp/index.html', {'foo': 'bar'})
# You can still modify the context here (or in middleware)
response.context_data['new_data'] = 123
return responseNOTE
TemplateResponse inherits from SimpleTemplateResponse. The main difference is that TemplateResponse requires the request object (ensuring context processors work), while SimpleTemplateResponse does not.
from django.template.response import SimpleTemplateResponse
def static_fragment_view(request):
# Renders 'my_fragment.html' with the given context
# No request object is passed to the template
return SimpleTemplateResponse('my_fragment.html', {'title': 'Static Info'})StreamingHttpResponse Object
The StreamingHttpResponse class is used to stream content to the browser rather than sending it all at once. This is essential for generating large responses (like CSV files or large data exports) without consuming excessive memory.
Unlike HttpResponse, which consumes the iterator immediately, StreamingHttpResponse streams the content from the iterator to the client over time.
from django.http import StreamingHttpResponse
def stream_view(request):
def content():
for i in range(1000):
yield f"Line {i}\n"
return StreamingHttpResponse(content(), content_type="text/plain")FileResponse Object
FileResponse is a subclass of StreamingHttpResponse optimized for sending binary files. It automatically handles file closing and sets appropriate headers (like Content-Length, Content-Type, and Content-Disposition) for you.
Automatic Attributes:
- It accepts a file path, an open file object, or a binary stream.
- If you pass
as_attachment=True, it sets theContent-Dispositionheader to prompt a "Save As" dialog in the browser. - It reads the file in chunks to minimize memory usage.
from django.http import FileResponse
def pdf_view(request):
return FileResponse(open("myfile.png", "rb"))Shortcut Functions
The django.shortcuts module provides helper functions to make your views concise. These shortcuts handle common patterns like loading templates or redirecting users.
render()
The render function is the most common way to return a response. It combines a template with a context dictionary and returns an HttpResponse object with the rendered text. It requires the request object and a template_name, but can accept a few optional arguments including context data dictionary.
from django.shortcuts import render
def my_view(request):
# Returns a 200 OK with rendered HTML
return render(request, "myapp/index.html", {
"foo": "bar",
}, content_type="application/xhtml+xml", status=200)NOTE
Django does not provide a shortcut function which returns a TemplateResponse because the constructor of TemplateResponse offers the same level of convenience as render().
redirect()
This function returns an HttpResponseRedirect to a specific URL. It requires a to argument which can be:
- A Model: The model's
get_absolute_url()function will be called. - A View Name:
reverse()will be used to resolve the name (args and kwargs can also be passed). - A URL: An absolute or relative URL path.
The function can also accept two optional arguments:
- permanent: Defaults to
False(temporary redirect). If set toTrue, a permanent redirect will be issued. - preserve_request: Defaults to
False. If set toTrue, the response instructs the user agent to preserve the method and body of the original request when issuing the redirect.
| permanent | preserve_request | HTTP Status Code |
|---|---|---|
False | False | 302 |
True | False | 301 |
False | True | 307 |
True | True | 308 |
from django.shortcuts import redirect
def my_view(request):
# 1. Redirect to an object (calls get_absolute_url)
obj = MyModel.objects.get(id=1)
return redirect(obj)
# 2. Redirect to a view name with arguments
return redirect('article-detail', pk=1)
# 3. Redirect to a hardcoded URL
return redirect('/some/url/')
# 4. Permanent redirect
return redirect('home', permanent=True)resolve_url()
This utility function returns a concrete URL string. It is used internally by redirect(), but you can use it directly if you need the URL string rather than a response object.
The to argument accepts the same types as redirect(): a model instance, a view name, or a raw URL.
from django.shortcuts import resolve_url
# Returns string: "/posts/1/"
url_string = resolve_url('post_detail', pk=1)
# Returns string: "/posts/1/" (calls obj.get_absolute_url())
url_string = resolve_url(my_model_instance)get_object_or_404()
This shortcut is useful for fetching a single object from the database. It calls the get() method on a model manager but raises a standard Http404 exception if the object does not exist. This replaces the need for a try-except block catching the DoesNotExist exception.
from django.shortcuts import get_object_or_404
def my_view(request):
obj = get_object_or_404(MyModel, pk=1)The shortcut above is equivalent to:
from django.http import Http404
def my_view(request):
try:
obj = MyModel.objects.get(pk=1)
except MyModel.DoesNotExist:
raise Http404("No MyModel matches the given query.")The Async version is named aget_object_or_404().
Using QuerySet
You can also pass a QuerySet instead of a model to filter the object further before retrieving it:
from django.shortcuts import get_object_or_404
def my_view(request):
# Pass a QuerySet (useful for permissions/filtering)
active_objects = MyModel.objects.filter(is_active=True)
obj = get_object_or_404(active_objects, pk=1)The above example is equivalent to:
from django.shortcuts import get_object_or_404
def my_view(request):
obj = get_object_or_404(MyModel, is_active=True, pk=1)Using Manager
You can also pass a Manager or a custom manager:
from django.shortcuts import get_object_or_404
def my_view(request):
# Uses the 'published' manager instead of the default 'objects'
obj = get_object_or_404(Post.published, pk=1)You can also use RelatedManager:
from django.shortcuts import get_object_or_404
def my_view(request):
# Pass a Related Manager
author = Author.objects.get(name="Roald Dahl")
obj = get_object_or_404(author.book_set, title="Matilda")get_list_or_404()
This function is similar to object retriever, but it uses filter() to return a list of objects. If the resulting list is empty, it raises an Http404 exception.
And similar to get_object_or_404(), it can accept a Model, Manager or a QuerySet instance.
The Async version is named aget_list_or_404().
from django.shortcuts import get_list_or_404
def my_view(request):
my_objects = get_list_or_404(MyModel, published=True)The above example is equivalent to:
from django.http import Http404
def my_view(request):
my_objects = list(MyModel.objects.filter(published=True))
if not my_objects:
raise Http404("No MyModel matches the given query.")