~4 min read • Updated Mar 14, 2026
Introduction
A view in Django is a Python function that receives a request and returns a response. This response can be an HTML page, a redirect, an image, an XML document, or any other type of content. Django does not impose restrictions on where view code must live; the only requirement is that it must be importable through the Python path. By convention, views are placed inside a file named views.py within an application directory.
A Simple View
The following example demonstrates a basic view that returns the current date and time as an HTML response:
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = '<html lang="en"><body>It is now %s.</body></html>' % now
return HttpResponse(html)How This View Works
- The
HttpResponseclass is imported fromdjango.http, along with Python’sdatetimemodule. - A function named
current_datetimeis defined. The name is arbitrary; Django does not require specific naming. - Every view receives an
HttpRequestobject as its first argument. - The function returns an
HttpResponsecontaining HTML.
Django uses the TIME_ZONE setting to determine the default timezone. You may adjust this value in your project’s settings file.
Mapping URLs to Views
To display a view at a specific URL, you must define a URLconf. This configuration maps URL patterns to view functions. Django processes incoming requests by matching the requested path against these patterns.
Returning Errors
Django provides subclasses of HttpResponse for common HTTP error codes. For example, HttpResponseNotFound represents a 404 response:
from django.http import HttpResponse, HttpResponseNotFound
def my_view(request):
if foo:
return HttpResponseNotFound("<h1>Page not found</h1>")
else:
return HttpResponse("<h1>Page was found</h1>")You can also specify a custom status code directly:
from django.http import HttpResponse
def my_view(request):
return HttpResponse(status=201)The Http404 Exception
Instead of manually returning a 404 response, Django allows you to raise the Http404 exception. Django catches this exception and displays the standard 404 error page.
from django.http import Http404
from django.shortcuts import render
from polls.models import Poll
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404("Poll does not exist")
return render(request, "polls/detail.html", {"poll": p})To customize the 404 page, create a template named 404.html at the root of your template directory. Django uses this template when DEBUG is set to False.
Customizing Error Views
You can override Django’s default error handlers by defining them in your root URLconf:
handler404 = "mysite.views.my_custom_page_not_found_view"
handler500 = "mysite.views.my_custom_error_view"
handler403 = "mysite.views.my_custom_permission_denied_view"
handler400 = "mysite.views.my_custom_bad_request_view"To override CSRF errors, use the CSRF_FAILURE_VIEW setting.
Testing Custom Error Views
You can test custom error handlers by raising exceptions in a test view:
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.test import SimpleTestCase, override_settings
from django.urls import path
def response_error_handler(request, exception=None):
return HttpResponse("Error handler content", status=403)
def permission_denied_view(request):
raise PermissionDenied
urlpatterns = [
path("403/", permission_denied_view),
]
handler403 = response_error_handler
@override_settings(ROOT_URLCONF=__name__)
class CustomErrorHandlerTests(SimpleTestCase):
def test_handler_renders_template_response(self):
response = self.client.get("/403/")
self.assertContains(response, "Error handler content", status_code=403)Asynchronous Views
Django supports asynchronous views using Python’s async def syntax. These views run in an ASGI environment and can improve performance when handling concurrent operations.
import datetime
from django.http import HttpResponse
async def current_datetime(request):
now = datetime.datetime.now()
html = '<html lang="en"><body>It is now %s.</body></html>' % now
return HttpResponse(html)For more details, refer to Django’s documentation on asynchronous support.
Written & researched by Dr. Shahin Siami