The HttpRequest Object
The HttpRequest object is the central data structure in this codebase for representing an incoming web request. Defined in django/http/request.py, it encapsulates all metadata, parameters, and headers provided by the client, providing a unified interface for both WSGI and ASGI handlers.
Core Request Attributes
When a request enters the system, the HttpRequest class (or one of its subclasses like WSGIRequest) populates several key attributes:
pathandpath_info: Strings representing the requested path.method: The HTTP method used (e.g., 'GET', 'POST').GETandPOST: Instances ofQueryDictcontaining query string and form data.COOKIES: A standard Python dictionary containing all cookies.META: A dictionary containing all available HTTP headers and environment variables.FILES: AMultiValueDictcontaining uploaded files.
Case-Insensitive Header Access
While raw headers are stored in the META dictionary (often prefixed with HTTP_), the HttpRequest.headers property provides a more convenient HttpHeaders interface.
The HttpHeaders class (a subclass of CaseInsensitiveMapping) allows for case-insensitive lookups and supports using underscores in place of hyphens.
# Accessing headers in a view
def my_view(request):
# These are all equivalent
user_agent = request.headers.get('User-Agent')
user_agent = request.headers.get('user-agent')
user_agent = request.headers.get('user_agent')
Internally, HttpHeaders handles the translation between standard header names and the HTTP_-prefixed keys found in the WSGI environment via the parse_header_name class method.
Handling Parameters with QueryDict
The GET and POST attributes are instances of QueryDict. This specialized subclass of MultiValueDict is designed to handle cases where a single key has multiple values (e.g., <select multiple>).
Multi-Value Access
Standard dictionary access (request.GET['key']) returns only the last value for a key. To retrieve all values, use getlist():
# URL: /search/?tag=python&tag=django
tags = request.GET.getlist('tag') # ['python', 'django']
Immutability
By default, QueryDict objects originating from an HttpRequest are immutable. Attempting to modify them directly will raise an AttributeError. To modify the data, you must create a mutable copy:
# Creating a mutable copy to add parameters
query_params = request.GET.copy()
query_params['new_param'] = 'value'
Content Negotiation
The HttpRequest class provides built-in support for content negotiation using the MediaType utility class. This allows views to determine what content types the client prefers based on the Accept header.
Preferred Types
You can check if a client accepts a specific type or find the best match from a list of options:
# Check if client accepts JSON
if request.accepts('application/json'):
return JsonResponse({'data': 'value'})
# Select the best match from available options
preferred = request.get_preferred_type(['text/html', 'application/json'])
The MediaType class handles the parsing of quality factors (q values) and specificity (e.g., text/* vs text/html) to determine precedence, as seen in the HttpRequest.accepted_types property.
Security and URI Management
Host Validation
The get_host() method retrieves the host of the request. It validates the host against the ALLOWED_HOSTS setting to prevent CSRF and cache poisoning attacks. If the host does not match any pattern in ALLOWED_HOSTS, a DisallowedHost exception is raised.
Absolute URIs
The build_absolute_uri() method is used to construct full URLs, which is particularly useful for redirects or generating links for emails. It automatically accounts for the current scheme (HTTP vs HTTPS) and host.
# Build an absolute URI for the current request
full_url = request.build_absolute_uri()
# Build an absolute URI for a specific path
login_url = request.build_absolute_uri('/accounts/login/')
Request Body and Streams
The raw body of the request can be accessed via the request.body property. However, there are critical constraints:
- Single Read: The body can only be read once. Accessing
request.bodyafter reading from the request's data stream (viaread()or by accessingPOST/FILES) will raise aRawPostDataException. - Size Limits: The system enforces a maximum size for the request body via the
DATA_UPLOAD_MAX_MEMORY_SIZEsetting. If theContent-Lengthexceeds this limit, aRequestDataTooBigexception is raised during the first attempt to read the body.
For large uploads or streaming data, the HttpRequest object provides a file-like interface with read(), readline(), and iteration support, which interfaces directly with the underlying _stream.