Writing your first Django app part 4 This tutorial begins where Tutorial 3 left off We re continuing the Web poll application and will focus on simple form processing and cutting down our code Write a simple form Let s update our poll detail template polls detail html from the last tutorial so that the template contains an HTML element poll question if error message error message endif csrf token for choice in poll choice set all input type radio name choice id choice forloop counter value choice id choice choice text endfor A quick rundown The above template displays a radio button for each poll choice The value of each radio button is the associated poll choice s ID The name of each radio button is choice That means when somebody selects one of the radio buttons and submits the form it ll send the POST data choice 3 This is the basic concept of HTML forms We set the form s action to url polls vote poll id and we set method post Using method post as opposed to method get is very important because the act of submitting this form will alter data server side Whenever you create a form that alters data server side use method post This tip isn t specific to Django it s just good Web development practice forloop counter indicates how many times the for tag has gone through its loop Since we re creating a POST form which can have the effect of modifying data we need to worry about Cross Site Request Forgeries Thankfully you don t have to worry too hard because Django comes with a very easy to use system for protecting against it In short all POST forms that are targeted at internal URLs should use the csrf token template tag Now let s create a Django view that handles the submitted data and Search Version Django 1 5 Search Contents Writing your first Django app part 4 Write a simple form Use generic views Less code is better Amend URLconf Amend views Browse Prev Writing your first Django app part 3 Next Writing your first Django app part 5 Table of contents General Index Python Module Index You are here Django 1 5 documentation Getting started Writing your first Django app part 4 Download Offline Django 1 5 HTML PDF ePub Provided by Read the Docs HomeDownloadDocumentationWeblogCommunityCode Writing your fi rst Django app part 4 Django documentation Django13 3 29 5 does something with it Remember in Tutorial 3 we created a URLconf for the polls application that includes this line url r P d vote views vote name vote We also created a dummy implementation of the vote function Let s create a real version Add the following to polls views py from django shortcuts import get object or 404 render from django http import HttpResponseRedirect HttpResponse from django core urlresolvers import reverse from polls models import Choice Poll def vote request poll id p get object or 404 Poll pk poll id try selected choice p choice set get pk request POST choice except KeyError Choice DoesNotExist Redisplay the poll voting form return render request polls detail html poll p error message You didn t select a choice else selected choice votes 1 selected choice save Always return an HttpResponseRedirect after successfully dealing with POST data This prevents data from being posted twice if a user hits the Back button return HttpResponseRedirect reverse polls results args p id This code includes a few things we haven t covered yet in this tutorial request POST is a dictionary like object that lets you access submitted data by key name In this case request POST choice returns the ID of the selected choice as a string request POST values are always strings Note that Django also provides request GET for accessing GET data in the same way but we re explicitly using request POST in our code to ensure that data is only altered via a POST call request POST choice will raise KeyError if choice wasn t provided in POST data The above code checks for KeyError and redisplays the poll form with an error message if choice isn t given After incrementing the choice count the code returns an HttpResponseRedirect rather than a normal HttpResponse HttpResponseRedirect takes a single argument the URL to which the user will be redirected see the following point for how we construct the URL in this case As the Python comment above points out you should always return an HttpResponseRedirect after successfully dealing with POST data This tip isn t specific to Django it s just good Web development practice We are using the reverse function in the HttpResponseRedirect constructor in this example This function helps avoid having to hardcode a URL in the view function It is given the name of the view that we want to pass control to and the variable portion of the URL pattern that points to that view In this case using the Writing your fi rst Django app part 4 Django documentation Django13 3 29 5 URLconf we set up in Tutorial 3 this reverse call will return a string like polls 3 results where the 3 is the value of p id This redirected URL will then call the results view to display the final page As mentioned in Tutorial 3 request is a HttpRequest object For more on HttpRequest objects see the request and response documentation After somebody votes in a poll the vote view redirects to the results page for the poll Let s write that view def results request poll id poll get object or 404 Poll pk poll id return render request polls results html poll poll This is almost exactly the same as the detail view from Tutorial 3 The only difference is the template name We ll fix this redundancy later Now create a polls results html template poll question for choice in poll choice set all choice choice text choice votes vote choice votes pluralize endfor Vote again Now go to polls 1 in your browser and vote in the poll You should see a results page that gets updated each time you vote If you submit the form without having chosen a choice you should see the error message Use generic views Less code is better The detail from Tutorial 3 and results views are stupidly simple and as mentioned above redundant The index view also from Tutorial 3 which displays a list of polls is similar These views represent a common case of basic Web development getting data from the database according to a parameter passed in the URL loading a template and returning the rendered template Because this is so common Django provides a shortcut called the generic views system Generic views abstract common patterns to the point where you don t even need to write Python code to write an app Let s convert our poll app to use the generic views system so we can delete a bunch of our own code We ll just have to take a few steps to make the conversion We will 1 Convert the URLconf 2 Delete some of the old unneeded views 3 Fix up URL handling for the new views Writing your fi rst Django app part 4 Django documentation Django13 3 29 5 Read on for details Why the code shuffle Generally when writing a Django app you ll evaluate whether generic views are a good fit for your problem and you ll use them from the beginning rather than refactoring your code halfway through But this tutorial intentionally has focused on writing the views the hard way until now to focus on core concepts You should know basic math before you start using a calculator Amend URLconf First open the polls urls py URLconf and change it like so from django conf urls import patterns url from django views generic import DetailView ListView from polls models import Poll urlpatterns patterns url r ListView as view queryset Poll objects order by pub date 5 context object name latest poll list template name polls index html name index url r P d DetailView as view model Poll template name polls detail html name detail url r P d results DetailView as view model Poll template name polls results html name results url r P d vote polls views vote name vote Amend views We re using two generic views here ListView and DetailView Respectively those two views abstract the concepts of display a list of objects and display a detail page for a particular type of object Each generic view needs to know what model it will be acting upon This is provided using the model parameter The DetailView generic view expects the primary key value captured from the URL to be called pk so we ve changed poll id to pk for the generic views By default the DetailView generic view uses a template called detail html In our case it ll use the template polls poll detail html The template name argument is used to tell Django to use a specific template name instead of the autogenerated default template name We also specify the template name for the results list view this ensures that the results view and the detail view have a different appearance when rendered even though they re both a DetailView behind the scenes Writing your fi rst Django app part 4 Django documentation Django13 3 29 5 Similarly the ListView generic view uses a default template called list html we use template name to tell ListView to use our existing polls index html template In previous parts of the tutorial the templates have been provided with a context that contains the poll and latest poll list context variables For DetailView the poll variable is provided automatically since we re using a Django model Poll Django is able to determine an appropriate name for the context variable However for ListView the automatically generated context variable is poll list To override this we provide the context object name option specifying that we want to use latest poll list instead As an alternative approach you could change your templates to match the new default context variables but it s a lot easier to just tell Django to use the variable you want You can now delete the index detail and results views from polls views py We don t need them anymore they have been replaced by generic views You can also de