An Introduction to Django – Part 3

In Part 3 of this introduction to Django series, we’ll look at making a simple form and also making views more generic.

Make a Simple Form

Lets put the form in the detail template.  Open the detail template (templates/polls/detail.html).  Change the file so that it looks like this:

This looks a lot worse than it really is.  Inside the form, there is a for loop that loops over each choice in the question.  It displays each choice as a radio button (this is the <input type = “radio” …> line).  When somebody submits the form, it will send the POST data choice = # where the # is the ID of the selected choice.

Now, we need to update our view so that it can handle the submitted data and do something with it.  Open polls/views.py to edit your views.

Add the following to the views file:

Here, we use request.POST[‘choice’] to grab the question ID of the selected choice.  The reverse() function within HttpResponseRedirect() lets us avoid hardcoding in a URL.  The inputs here are a view name and the variable portion of the URL pattern for that view.

This view redirects a user to the results page after they submit a vote.  To make that view, add the following to polls/views.py:

And now we need to create this template.  Create a file /templates/polls/results.html that has the following in it:

Now navigate to http://localhost:8000/polls/1/ and vote.  You should be redirected to the results page where it shows the total votes.  If you try to vote without making a choice, you should receive an error.

At this point, our simple polling app has all of the base functionality to work as we want.  Now, lets go over the views and see if we can clean up the code by making them more generic.

Use Generic Views

As with any other kind of programming, it is a good idea to generalize something that will be used more than once (if possible).  The same is of course true for views.

If we look at our views, we can see that the detail and results views are really similar.  Keeping them as is would be redundant, so lets make one view that we can use for both.

Luckily, this is so common that Django has provided a shortcut called the ‘generic views system’.  To use this, we will need to follow two steps:

1 Convert the URLconf

Open polls/urls.py and change it to look like this:

In addition to adding .__View to the views object, we also changed the <question_id> to simply <pk> to make this be more generic.

2 Amend The Views

Open the polls/views.py file.  We need to remove the old indexdetail, and results views and use our new generic view instead.

Notice that we changed these from functions (using def) to classes (using class).  Next, notice that we are using two different generic views (ListView and DetailView).  The ListView is a generic view for displaying a list of objects and DetailView is a generic view for displaying a detail page for a type of object.

Each generic view needs to know what model it will act on, using the model attribute.  Also, the DetailView expects a primary key value from the URL to be called pk, which is why we changed the question_id to pk in the URLconf.

The DetailView generic view uses a template by default called <app name>/<model name>_detail.html.  For us, that will be polls/question_detail.html.  If you don’t want to use this default one, you can specify which template to use by using the template_name variable, which we do in each of the classes.

That’s it for this portion.  Django is still very difficult for me to grasp.  I feel like if I were trying to do my own app, I wouldn’t know all of these details (like template_name and context_object_name).  I haven’t checked the documentation, but I’m hopeful that it is good enough that when I’m ready to do my own app, I’ll feel more confident.

Next time, we’ll look at automated tests, what they are, why they are good, and how to use them.

Have questions or suggestions?  Please feel free to comment below or contact me.

Leave a Reply

Your email address will not be published. Required fields are marked *