You probably know by now that all backend technologies and web APIs are based on the request and response objects. You'll also often come across them when you start building web applications with Django. These objects are responsible for data interchange between client machines and servers. Request and response objects are transmitted over the web. Let's explore the fundamental concepts of the Django HTTP request and response objects, including how to create, manipulate, and work with them in your applications.
Request and response objects
HTTP requests are a fundamental part of any web application, and Django provides a rich API for working with them. When users visit your website, their web browser sends an HTTP request to your server. The server processes this request and sends back an HTTP response which the browser uses to render the page.
Django HttpRequest objects represent incoming requests from clients. These objects contain all the information about the request, including the headers, URL, and any data in the request body. You can access this information through various properties of the HttpRequest object like the HttpRequest.method to get the method used in the request (for example, GET, POST, PUT, DELETE), HttpRequest.GET that returns a dictionary-like object containing any query parameters included in the request URL or HttpRequest.POST to produce a dictionary-like object containing any form of data included in the request body.
HTTP responses, on the other hand, are sent back to clients in response to HTTP requests. They contain the data the client's browser will use to render the page. Django provides HttpResponse objects to make it easy to create and send responses.
HttpResponse objects can contain any content, including HTML, JSON, and binary data. You can also set various HTTP headers on the response to control how the client's browser processes it.
Django HttpResponse class
Django HttpResponse class is a part of the django.http module; it handles a text response of an HTTP request. This class is most frequently used as a return object from the Django view.
Unlike automatically created HttpRequest objects, HttpResponse objects are developed manually. Each view you write for your Django app is responsible for doing one of two things: returning an HttpResponse object with the content of the requested page or raising an exception.
Content like images, videos, HTML, CSS, and JavaScript are HttpResponse objects.
Now, we add the path for the view inside the urls.py file:
# first we need to import the view function
from responses import http_response
# we create the path to our view function
urlpatterns = [
#other paths
...
path('http_response/', http_response, name='response'),
]The HttpResponse class has three main aspects:
The status code is a three-digit number representing the HTTP response's status. It tells the client whether the request was successful and, if not, what went wrong. Django provides a list of standard HTTP status codes that can be used with the HttpResponse class, such as
200forOKor404forNot Found. You can set the status code in the constructor of theHttpResponseclass.The content is the data that will be returned to the client as part of the HTTP response. This can be any data converted to a string, such as text, HTML, or JSON. You can set the content in the constructor of the
HttpResponseclass.
Let's imagine we have a Django app named responses . We create the view function http_response inside the views.py file in our app:
from django.http import HttpResponse
def http_response(request):
return HttpResponse('Hello HttpResponse') The HttpResponse class passes the page's content as a string or a byte string to the constructor. To add the content to the page incrementally, the response can be used as a file-like object:
from django.http import HttpResponse
def http_response(request):
response = HttpResponse()
response.write("<p>Hello, World!</p>")
response.write("<p>Hello, World Wide Web II!</p>")
return response
The
HttpResponseclass can also be used to set a header in the response object. Using the response object as a dictionary, we can manipulate header fields. In other words, we can add or delete headers of the response object:
from django.http import HttpResponse
def http_response(request):
response = HttpResponse()
response['Name'] = 'Andrei'
response['Location'] = 'some location'
del response['Location']
return responseUnlike in dictionaries, the del command can delete a non-existing header in objects. It won't raise an error.
Do not use newlines in the HTTP header fields. If you try to set a header with newline characters, Django will raise a BadHeaderError.
Starting with Django 3.2, developers added the HttpResponse.headers attribute. This attribute is a case-insensitive dictionary-like object that provides an interface to all HTTP headers of the response object:
from django.http import HttpResponse
def http_response(request):
response = HttpResponse()
response.headers['Name'] = 'Andrei'
response.headers['Location'] = 'some location'
del response.headers['Location']
return responseAlong with the HttpResponse.headers attribute, there's an ability to set headers when an HttpResponse object is instantiated:
from django.http import HttpResponse
def http_response(request):
response = HttpResponse(headers={'Name': 'Andrei', 'Location': 'Italy'})
return responseIn the next section, we will point out some other important attributes and methods of the Httpresponse class.
HttpResponse attributes and methods
Like any other class, HttpResponse has many attributes and methods. Django does a lot of work when you use this class, but it is worth mentioning some of its attributes and methods that can be used for advanced manipulation of the response object.
Among HttpResponse attributes, it is worth mentioning:
HttpResponse.contentreturns the content of the response as a byte string;HttpResponse.charsetspecifies the character encoding used to interpret the response content;HttpResponse.status_codesets or gets the HTTP status code for the response (e.g., 200 for success, 404 for not found);HttpResponse.closedisTrueif the response has been closed andFalse, if otherwise;HttpResponse['Content-Type']sets or gets the MIME type of the response content;HttpResponse.set_cookie()sets a cookie on the client's browser;HttpResponse.delete_cookie()deletes a cookie previously set on the client's browser.
Some of the most valuable methods of the HttpResponse class are:
HttpResponse.__init__(content=”", content_type=None, status=200, reason=None, charset=None)instantiates anHttpResponseobject with the page content and content type;HttpResponse.__setitem__(header, value)sets the provided header name to the value;HttpResponse.__delitem__(header)deletes a header with the provided name;HttpResponse.__getitem__(header)returns the value of the header name;HttpResponse.getvalue()retrieves the value of theHttpResponse.contentattribute.
You can read more about these methods and attributes and explore others on the official documentation page.
HttpResponse subclasses
Django contains a range of HTTPResponse subclasses to handle different types of HTTP responses. As with the HttpResponse class, these subclasses are present in django.http. All these subclasses act just like the HttpResponse class but return different response codes. Let's take a look at some of them.
HttpResponse can be used to return an HTML response. This is often used to render a template with the context data and return the rendered HTML:
from django.http import HttpResponse
from django.shortcuts import render
def http_response(request):
context = {'name': 'Andrei'}
return render(request, 'template.html', context=context)HttpResponse can also be used to return JSON data. This is often used in APIs to return structured data to the client:
from django.http import HttpResponse
import json
def http_response(request):
data = {'name': 'Andrei', 'location': 'Italy'}
json_data = json.dumps(data)
return HttpResponse(json_data, content_type='application/json')HttpResponseForbidden uses the 403 status code. The code indicates that the server understands the request but refuses to authorize it. This is often used to restrict access to specific resources:
from django.http import HttpResponseForbidden
def http_response(request):
if not request.user.is_authenticated:
return HttpResponseForbidden()Lastly, we will mentionHttpResponseRedirect that takes a path to redirect as the first argument. This can be a full URL (https://www.hyperskill.org/search), an absolute path with no domain (/search/), or even a relative path. In the last case, the browser will reconstruct the full URL according to the current path. This returns the HTTP status code 302 that indicates that the resource requested has been temporarily moved to the location specified in the first argument:
def http_response(request):
return HttpResponseRedirect("https://www.google.com")A list containing all subclasses can be found on the official documentation page.
Conclusion
The Django HttpResponse class provides robust tools for generating and dispatching HTTP responses. It simplifies the process of setting response attributes such as status code, content, headers, cookies, and other response properties. By leveraging the power of the HttpResponse class, developers can create customized and sophisticated responses that can be tailored to the specific needs of their applications. This includes responses that provide different types of content, such as text, HTML, images, and even JSON data.