Django 1.10 Chinese Document-First Application Part4-form and general view, djangopart4-

Source: Internet
Author: User

Django 1.10 Chinese Document-First Application Part4-form and general view, djangopart4-

This tutorial starts with Part3. Continue to the Web Page Voting application, and focus on simple form processing and streamlined code.

A simple form

Update the template of the vote details page written in the previous tutorial.polls/detail.htmlTo includeHTML<form>Element:

# polls/templates/polls/detail.html

The above code:

  • In the template, each Choice of Question has a single Choice button for selection. The value Attribute of each radio button corresponds to the ID of each Choice. The name of each radio button is "choice ". This means that when someone selects a single-choice button and submits the form for submission, it will send a POST data Choice = #, where # is the ID of the selected choice. This is the basic concept of HTML forms;

  • Action indicates the destination url you want to send, and method indicates the data submission method;

  • Forloop. counter indicates the number of for loops;

  • Since we have sent a POST request, we must consider the issue of Cross-Site Request Forgery (CSRF ). Django provides you with a simple way to avoid this problem, that is, to add a {% csrf_token %} tag to the form, the tag name cannot be changed, the format is fixed, and the location is arbitrary, as long as it is in the form.

Now, create a Django view to process the submitted data. In Part3, you have created a URLconf containing this line:

# polls/urls.pyurl(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),

Modify the vote () function. Add the following code to polls/views. py:

# Polls/views. pyfrom django. shortcuts import get_object_or_404, renderfrom django. http import HttpResponseRedirect, HttpResponsefrom django. urls import reversefrom. models import Choice, Question #... def vote (request, question_id): p = get_object_or_404 (Question, pk = question_id) try: selected_choice = p. choice_set.get (pk = request. POST ['choice ']) handle T (KeyError, choice. doesNotExist): # re-display the voting form when an exception occurs. Return render (request, 'lls/detail.html ', {'Question': p, 'error _ message': "You did' t select a choice. ",}) else: selected_choice.votes + = 1 selected_choice.save () # After data is processed successfully, the results page is automatically displayed to prevent users from submitting data multiple times. Return HttpResponseRedirect (reverse ('polls: results', args = (p. id ,)))

Some of the above code needs to be explained:

  • Request. POST is a dictionary-like object that allows you to access submitted data with a key name. Coderequest.POST['choice']Returns the ID of the selected Choice, and the value type is always a string;

  • If choice is not provided in POST data,request.POST['choice']A KeyError is thrown. The abovetry ... exceptIt is used to check KeyError. If choice is not given, the Question form and error information will be re-displayed;

  • After adding the number of Choice votes to 1, an HttpResponseRedirect instead of a common HttpResponse is returned. HttpResponseRedirect only receives one parameter: the URL to be redirected;

  • In this example, the HttpResponseRedirect constructor uses the reverse () function. This function avoids hard URL encoding in view functions. It requires us to give the name of the view to jump to and the parameters that need to be provided to the view in the URL mode corresponding to the view. In this example, using the URLconf set in Part3, the reverse () call will return a string like this:'/polls/3/results/'.

After voting for Question, the vote () view redirects the request to the result interface of Question. Write this view as follows:

#polls/views.pyfrom django.shortcuts import get_object_or_404, renderdef results(request, question_id):    question = get_object_or_404(Question, pk=question_id)    return render(request, 'polls/results.html', {'question': question})

This is almost the same as the detail () view. The only difference is the Template Name. Try again later. Create a polls/results.html template as follows:

# polls/templates/polls/results.html

Now, access/polls/1/in the browser and vote for Question. You should see a page of voting results, which will be updated after each vote. If no Choice is selected during submission, the error message is displayed.

Note: The views () view code does have a small problem. It first obtains the selected_choice object from the database, calculates the new voting value, and writes it back to the database. If two users on your website try to vote at the same time, this may cause an error. This is called a competitive condition. If you are interested, read and use F () to avoid competition conditions to learn how to solve this problem;

Use common view: reduce code Redundancy

The code of the detail, index, and results view above is very similar and redundant, which is intolerable by programmers. They all have similar business logic and implement similar functions: query data in the database by passing parameters from the URL, load a template, use the Data Rendering template just now, and return this template. Because this process is so common, Django helps you find a way to be lazy. It provides a shortcut namedgeneric viewsSystem.

Generic views abstracts common patterns so that you do not even need to write Python code when writing an app.

The following code converts a voting application to a general view system, which can delete a lot of redundant code. You only need to perform the following steps to complete the conversion:

  • Modify URLconf;

  • Delete old useless views;

  • Use a new view based on a general view.

Improved URLconf
# polls/urls.pyfrom django.conf.urls import urlfrom . import viewsapp_name = 'polls'urlpatterns = [    url(r'^$', views.IndexView.as_view(), name='index'),    url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),    url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),]

Note that in the regular expressions of the second and third modes<question_id>Change<pk>

Improved View

The old index, detail, and results views will be deleted and replaced with the common view of Django:

# polls/views.pyfrom django.shortcuts import get_object_or_404, renderfrom django.http import HttpResponseRedirectfrom django.urls import reversefrom django.views import genericfrom .models import Choice, Questionclass IndexView(generic.ListView):    template_name = 'polls/index.html'    context_object_name = 'latest_question_list'    def get_queryset(self):        """Return the last five published questions."""        return Question.objects.order_by('-pub_date')[:5]class DetailView(generic.DetailView):    model = Question    template_name = 'polls/detail.html'class ResultsView(generic.DetailView):    model = Question    template_name = 'polls/results.html'def vote(request, question_id):    ... # same as above, no changes needed.

Two general views are used: ListView and DetailView. These two views represent the abstract concepts of "Display object list" and "display details page of specific types of objects" respectively.

  • Each common view needs to know which model it will act on. This is provided by the model attribute;

  • DetailView captures the primary key value named "pk" from the URL. Therefore, you need to change question_id in polls/urls. py to the primary key value so that the general view can find the primary key value.

By default, the DetailView generic view uses<app name>/<model name>_detail.html. In this examplepolls/question_detail.html. The template_name attribute is used to specify the Template Name, instead of the automatically generated default Template Name.

In the previous section of the tutorial, we provided the template with a context variable containing question and latest_question_list. For DetailView, the question variable is automatically provided. Because we use the Django model (Question), Django intelligently selects the appropriate context variable. However, for ListView, The automatically generated context variable is question_list. To overwrite it, we provide the context_object_name attribute, specifying that we want to use latest_question_list instead of question_list.

Now you can run the development server and try the application based on the generic view.

  

Related Article

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.