Actual combat Django: official Example Part4

Source: Internet
Author: User

The previous part we created the voting content page, but this page is limited to static display, voting "cast" word is not reflected. Next, let's take a look at how to cast the tickets.

19. Create a form

Let's update the template file polls/detail.htmlto include the "form" element:

polls/templates/polls/detail.html :

<H1>{{Question.question_text}}</H1>{% if error_message%}<P><Strong>{{Error_message}}</Strong></P>{% endif%}<formAction= "{% url ' polls:vote ' question.id%}"Method= "POST">{% Csrf_token%}{% for choice in question.choice_set.all%}<inputtype= "Radio"name= "Choice"ID= "choice{{Forloop.counter}}"value= "{{choice.id}}" />    <label for= "choice{{Forloop.counter}}">{{Choice.choice_text}}</label><BR/>{% endfor%}<inputtype= "Submit"value= "vote" /></form>

A brief explanation:

    • In the above template, we add a radio button to each voting item, each radio button is associated to the number of the voting item, the name of the radio button is called "Choice", so when a user selects a poll and submits the form (that is, the poll), it sends a set of "choice=#" (# Data, which is the basic concept of HTML forms.
    • We set the action of the form to "{% url ' polls:vote ' question.id%}", set its method to "post" and "post" means that the user submits this data to the server side.
    • Forloop.counter shows the number of times for the For loop.
    • When we use post to submit a form, we need to consider the risk of cross-site request forgery. But don't worry, Django has already taken this into account for us, so you can avoid the risk by adding "{% Csrf_token}" tags to the template.

Note, don't forget to save the template file as Utf-8 encoding.

Next, we modify the corresponding view, edit the polls/views.py file, and change it to the following:

polls/views.py:

 fromDjango.shortcutsImportget_object_or_404, Render fromDjango.httpImportHttpresponseredirect, HttpResponse fromDjango.core.urlresolversImportReverse fromPolls.modelsImportChoice, Question# ...defvote (Request, question_id): P= get_object_or_404 (Question, pk=question_id)Try: Selected_choice= P.choice_set.get (pk=request. post['Choice'])    except(Keyerror, choice.doesnotexist):#If no voting items are selected, the poll form is displayed again.        returnRender (Request,'polls/detail.html', {            'question': P,'error_message':"You didn ' t select a choice.",        }) Else: Selected_choice.votes+ = 1Selected_choice.save ()#after a successful commit, a Httpresponseredirect object with post data is returned.
        # prevents users from submitting data two times when they use the return command. 
        return Httpresponseredirect (Reverse ('polls:results', args= (P.id,)))

To explain:

    • Request. Post is a dictionary-like object, in this case you can use request. post[' Choice ' to get the number of the selected voting item.
    • Request when a user submits a poll and does not select any voting items. post[' Choice ' will throw a Keyerror exception, and we'll re-display the voting form.
    • When the vote is successful, the number of votes in the currently selected ballot is automatically added to 1, after which we return a Httpresponseredirect object (instead of the httpresponse we used previously), and this httpresponseredirect only takes one parameter, is the page link that we want the user to see after the user polls.
    • In Httpresponseredirect we use the reverse () function, which we use to generate the page link described above, in this case the reverse () returns the character as follows:
' /polls/3/results/ '

The above 3 comes from the "p.id" parameter, which invokes the "Results" view to display the final page.

When the user finishes voting, the vote view will move the link to the results page, and then we'll write a view of the resulting page.

Edit polls/views.py file:

polls/views.py:

 from Import get_object_or_404, Render def results (Request, question_id):     = get_object_or_404 (Question, pk=question_id)    return'polls/results.html  ', {'question': Question})

This view is very much like the detail view we described earlier, except that the template name is different.

We then put the corresponding template on the view. Create a template file polls/results.html, adding the following:

polls/templates/polls/results.html :

<H1>{{Question.question_text}}</H1><ul>{% for choice in question.choice_set.all%}<Li>{{Choice.choice_text}}--{{choice.votes}} vote{{Choice.votes|pluralize}}</Li>{% endfor%}</ul><ahref= "{% url ' polls:detail ' question.id%}">One more shot?</a>

Below, let's visit the link http://127.0.0.1:8000/polls/1/and start voting:

After a successful vote, we can see the page automatically jumps to the results page, where we can see the poll data:

You can also try to find out what happens when you click the Vote button.

20. Use a common view to streamline your code

In web development, we pursue the idea of "less code is better". The detail view in Part3 is very similar to the results view here, but the code is slightly redundant and can be streamlined. The same can be streamlined with our index view.

Django provides us with a generic view that we can use to make the code more concise by using a common view in the polls application.

To use a common view, we need to do the following:

    • Convert the URL configuration file;
    • Delete some views that you do not need;
    • Introduction of a common view;

First let's adjust the URL configuration file, edit the polls/urls.py file, change to this:

polls/urls.py:

 fromDjango.conf.urlsImportpatterns, url fromPollsImportViewsurlpatterns= Patterns ("', the URL (r'^$', views. Indexview.as_view (), name='Index'), url (r'^(? p<pk>\d+)/$', views. Detailview.as_view (), name='Detail'), url (r'^(? p<pk>\d+)/results/$', views. Resultsview.as_view (), name='Results'), url (r'^(? p<question_id>\d+)/vote/$', Views.vote, Name='vote'),)

Notice that the regular expression in the URL has changed, and in the second to third regular expression, we have changed <question_id> to <pk>.

Next, we'll remove the index,detail,results view and replace it with a generic view of Django. Edit the polls/views.pyand change it to the following:

polls/views.py:

 fromDjango.shortcutsImportget_object_or_404, Render fromDjango.httpImportHttpresponseredirect fromDjango.core.urlresolversImportReverse fromDjango.viewsImportGeneric fromPolls.modelsImportChoice, QuestionclassIndexview (Generic. ListView): Template_name='polls/index.html'Context_object_name='latest_question_list'    defGet_queryset (self):"""Return The last five published questions."""        returnQuestion.objects.order_by ('-pub_date') [: 5]classDetailView (Generic. DetailView): Model=Question template_name='polls/detail.html'classResultsview (Generic. DetailView): Model=Question template_name='polls/results.html'

We used two common views, ListView and DetailView. The previous view displays a set of objects in a list, and the latter view is used to display the details of a particular object.

    • Each view needs to know which model it will operate on, so we provide it with model properties;
    • DetailView need to get the primary key value (PK) from the link, which is why we changed <question_id> to <pk> in the urls.py.

If you do not specify the Template_name attribute for DetailView, it will use the < app name >/< model name >_detail.html as the template name, in this case the default template name will look like this: polls/ Question_detail.html. Because our detail view and results view both use DetailView, we want to assign template_name to each of them so that they can present their content in different templates.

Similarly, if you do not specify the Template_name property for the ListView, it uses the < apply name >/< model name >_list.html as the template name, and we assign the index view Template_ Name property, let it use the "polls/index.html" template that we have already done.

In Part3, our view passes the question and latest_question_list variables to the template, and in Deltailview we don't need to pass the question variable, which is automatically sent to the template. However, in the ListView, the variable that it submits automatically to the template is question_list--this is a complete list, and we just need to provide the latest 5 to suffice. We wanted to replace the default question_list with Latest_question_list, so we gave the template a Context_object_name property.

By doing this, let's look at the results of our work again in the browser.

In Part5, we are willing to tell you how to test our voting application.

"Not to be Continued"

This article copyright to willing to learn all, welcome reprint, reproduced please indicate the author and source. Thank you!
Willing
Starter: Willing to learn Yuan @ Blog Park

Actual combat Django: official Example Part4

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.