Writing Views§

Handling HTTP Requests from users.

View Basics§

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.

Generic & Class Based Views§

Class Based Views§

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.

List Views

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 <model name>_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

Edit Views

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 <model name>
    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()

Detail Views

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 <model name>

    def get_context_data(self, **kwargs):
        ... # add anything else to the context

Defining URLs§

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',),
)

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.

Django Templates

Test Client & RequestFactory

Test Client vs. RequestFactory

from 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)

Live Server Tests