Writing Views§
Handling HTTP Requests from users.
Handling HTTP Requests from users.
Django Views take an HTTP Request and return an HTTP Response to the user.
Any Python callable can be a view. The only hard and fast requirement is that it takes the request object (customarily named request
) as its first argument. This means that a minimalist view is super simple:
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello, World")
Of course, like most frameworks, Django also allows you to pass arguments to the view from the URL. We'll cover this as we build up our application.
The minimal class based view subclasses View and implements methods for the HTTP methods it supports. Here's the class-based version of the minimalist "Hello, World" view we previously wrote.
from django.http import HttpResponse
from django.views.generic import View
class MyView(View):
def get(self, request, *args, **kwargs):
return HttpResponse("Hello, World")
In a class based view, HTTP methods map to class method names. In this case, we've defined a handler for GET
requests with the get
method. Just like the function implementation, it takes request
as its first argument, and returns an HTTP Response.
Permissive Signatures
You may notice that it has a couple of extra arguments in its signature, compared to the view we saw previously, specifically *args
and **kwargs
. Class based views were first introduced as a way to make Django's "generic" views more flexible. That meant they were used in many different contexts, with potentially different arguments extracted from the URLs. As I've been writing class based views over the past year, I've continued to write them with permissive signatures, as I've found they're often useful in ways I didn't initially expect.
ListView provides a view of a set of objects.
class ContactsList(ListView):
model = Contact
template_name = 'contact_list.html'
def get_queryset(self):
... # defaults to model.objects.all()
def get_context_object_name(self):
... # defaults to _list
def get_context_data(self, **kwargs):
... # add anything else to the context
def get_context_data(self, **kwargs):
... # add anything else to the context
CreateView, UpdateView, DeleteView work on a model instance.
class UpdateContact(UpdateView):
model = Contact
template_name = 'edit_contact.html'
def get_object(self):
... # defaults to looking for a pk or slug kwarg, and
# passing that to filter
def get_context_object_name(self):
... # defaults to
def get_context_data(self, **kwargs):
... # add anything else to the context
def get_success_url(self):
... # where to redirect to on success
# defaults to self.get_object().get_absolute_url()
DetailView provides a view of a single object
class ContactView(DetailView):
model = Contact
template_name = 'contact.html'
def get_object(self):
... # defaults to looking for a pk or slug kwarg, and
# passing that to filter
def get_context_object_name(self):
... # defaults to
def get_context_data(self, **kwargs):
... # add anything else to the context
The URL configuration tells Django how to match a request's path to your Python code. Django looks for the URL configuration, defined as urlpatterns
, in the urls.py
file in your project.
Let's add a URL mapping for our contact list view in addressbook/urls.py
.
from django.conf.urls import patterns, include, url
import contacts.views
urlpatterns = patterns('',
url(r'^$', contacts.views.ListContactView.as_view(),
name='contacts-list',),
)
url()
function is not strictly required, but I like it: when you start adding more information to the URL pattern, it lets you use named parameters, making everything more clear.$
; why might that be important?as_view()
, which returns a wrapper around our class that Django's URL dispatch can call.While the urlpatterns
name must be defined, Django also allows you to define a few other values in the URL configuration for exceptional cases. These include handler403
, handler404
, and handler500
, which tell Django what view to use when an HTTP error occurs. See the Django urlconf documentation for details.
URL Configuration Import Errors
Django loads the URL configuration very early during startup, and will attempt to import things it finds here. If one of the imports fails, however, the error message can be somewhat opaque. If your project stops working with an import-related exception, try to import the URL configuration in the interactive shell. That usually makes it clear where the problem lies.
TEMPLATE_DIRS
to look for templates intemplate
subdirectory in each appClient
and RequestFactory
are tools to help test themClient
resolves a URL to the view, returns a ResponseRequestFactory
generates a Request which you can pass to the View directlyfrom django.test.client import Client
from django.test.client import RequestFactory
client = Client()
response = client.get('/')
factory = RequestFactory()
request = factory.get('/')
response = ListContactView.as_view()(request)
runserver
)