Django快速入門-表單

在上一節(jié)的教程中,我們介紹了 Django的視圖,并編寫了一個(gè)簡單的實(shí)例。本小節(jié)我們將學(xué)習(xí)網(wǎng)絡(luò)投票應(yīng)用程序,并將側(cè)重于簡單的表單處理,以最少代碼代碼量來實(shí)現(xiàn)。

編寫一個(gè)簡單的表單

讓我們更新 poll detail 模板(“polls/detail.html”) ,從上個(gè)教程,在模板 polls/templates/polls/detail.html 包含一個(gè)HTML<form>元素:

# Filename : example.py
# Copyright : 2020 By Nhooo
# Author by : www.soo66.com
# Date : 2020-08-08
<h1>{{ question.question_text }}</h1>
 {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
 <form action="{% url 'polls:vote' question.id %}" method="post">
 {% csrf_token %}
 {% for choice in question.choice_set.all %}
     <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
     <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
 {% endfor %}
 <input type="submit" value="Vote" />
 </form>上面的模板顯示每個(gè)問題選擇一個(gè)單選按鈕。每個(gè)單選按鈕的值相聯(lián)問題的選擇編號。每個(gè)單選按鈕的名稱是“choice”。這意味著,當(dāng)有人選擇了其中一個(gè)單選按鈕并提交表單,它會(huì)發(fā)送POST數(shù)據(jù)choice=#,其中#是被選擇的選擇的ID。這是HTML表單的基本概念。  
  我們設(shè)置表單的動(dòng)作 {% url 'polls:vote' question.id %}, 以及設(shè)置 method="post". 使用 method="post" (相對于 method="get") 是非常重要的,因?yàn)樘峤淮吮韺⒏淖兎?wù)器端數(shù)據(jù)的行為。當(dāng)創(chuàng)建一個(gè)改變數(shù)據(jù)服務(wù)器端表單形式,使用 method="post". 這篇文章并不是只針對 Django; 這是一個(gè)很好的 Web 開發(fā)實(shí)踐。  
  forloop.counter表示表單標(biāo)簽通過多少次循環(huán)了  
  因?yàn)槲覀冋趧?chuàng)建一個(gè)POST形式(可以有修改數(shù)據(jù)的影響),我們需要擔(dān)心跨站點(diǎn)請求偽造。但是也不必?fù)?dān)心,因?yàn)镈jango自帶了保護(hù)對抗的一個(gè)非常容易使用的系統(tǒng)。總之,這是針對內(nèi)部URL所有的POST形式應(yīng)該使用{%csrf_token%}模板標(biāo)簽。

我們還創(chuàng)建了一個(gè)虛擬實(shí)現(xiàn) vote() 函數(shù)?,F(xiàn)在創(chuàng)建一個(gè)實(shí)用的版本。添加到以下代碼到文件 polls/views.py:

polls/views.py 文件的內(nèi)容如下:

# Filename : example.py
# Copyright : 2020 By Nhooo
# Author by : www.soo66.com
# Date : 2020-08-08
from django.shortcuts import get_object_or_404, render
 from django.http import HttpResponseRedirect, HttpResponse
 from django.core.urlresolvers import reverse
 from .models import Choice, Question
 # ...
 def vote(request, question_id):
     question = get_object_or_404(Question, pk=question_id)
     try:
         selected_choice = question.choice_set.get(pk=request.POST['choice'])
     except (KeyError, Choice.DoesNotExist):
         # Redisplay the question voting form.
         return render(request, 'polls/detail.html', {
             'question': question,
             '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=(question.id,)))

此代碼包含還沒有在本教程中涉及幾個(gè)東西:

request.POST是一個(gè)類似于字典的對象,使您可以通過鍵名訪問提交的數(shù)據(jù)。在這種情況下,request.POST['choice'] 返回被選擇的choice的ID,作為字符串。 request.POST的值總是字符串。 

注意:Django還提供 request.GET 以相同的方式訪問 GET數(shù)據(jù)  – 但我們明確使用 request.POST 在我們的代碼,以確保數(shù)據(jù)只能通過POST調(diào)用修改。

如果POST數(shù)據(jù)未提供choice,request.POST['choice']將引發(fā)KeyError異常。上面的代碼檢查KeyError異常和錯(cuò)誤消息顯示問題的表單,如果沒有給出   choice。

選擇choice計(jì)數(shù)遞增后,代碼返回 HttpResponse 重定向,而不是一個(gè)正常的 HttpResponse。HttpResponseRedirect 需要一個(gè)參數(shù):用戶將被重定向到URL(請參閱下面-我們?nèi)绾螛?gòu)建在這種情況下的URL)。

如上Python的注釋所指出的,應(yīng)該總是在 POST 數(shù)據(jù)處理成功  后返回一個(gè)HttpResponse重定向。

在本示例中我們使用的是 HttpResponseRedirect 構(gòu)造reverse()函數(shù)。此函數(shù)有助于避免硬編碼URL在視圖中。這是因?yàn)槲覀兿胪ㄟ^控制并指向該視圖的URL模式的可變部分的視圖的名稱。在這種情況下,使用 URLconf 配置使 reverse()調(diào)用返回字符串如:

# Filename : example.py
# Copyright : 2020 By Nhooo
# Author by : www.soo66.com
# Date : 2020-08-08
'/polls/3/results/'

其中3是question.id的值。然后,這個(gè)重定向的URL將調(diào)用“results”視圖中顯示的最后一頁。

現(xiàn)在訪問網(wǎng)址:http://127.0.0.1:8000/polls/1/ 得到結(jié)果如下所示:  瀏覽器運(yùn)行結(jié)果 當(dāng)有人在一個(gè)問題投票后,vote() 視圖重定向到該問題的結(jié)果頁面。讓我們編寫這個(gè)視圖(polls/views.py):

# Filename : example.py
# Copyright : 2020 By Nhooo
# Author by : www.soo66.com
# Date : 2020-08-08
from django.shortcuts import get_object_or_404, render
 def results(request, question_id):
     question = get_object_or_404(Question, pk=question_id)
     return render(request, 'polls/results.html', {'question': question})

現(xiàn)在,創(chuàng)建一個(gè) polls/results.html (polls/templates/polls/results.html)模板:

# Filename : example.py
# Copyright : 2020 By Nhooo
# Author by : www.soo66.com
# Date : 2020-08-08
<h2>{{ question.question_text }}</h2>
 <ul>
 {% for choice in question.choice_set.all %}
     <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
 {% endfor %}
 </ul>
 <a href="{% url 'polls:detail' question.id %}">Vote again?</a>

現(xiàn)在,在瀏覽器中打開 /polls/1/ 并表決的問題。應(yīng)該會(huì)被每次投票時(shí)看到更新結(jié)果頁。如果您提交表單不選擇一個(gè)選項(xiàng),應(yīng)該看到錯(cuò)誤消息。 選擇選項(xiàng),提交后顯示如下結(jié)果:  瀏覽器運(yùn)行結(jié)果

使用通用視圖:更少的代碼更好

修改URL配置

首先,打開 polls/urls.py 并修改如下:

from django.conf.urls import url
from . import views

app_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'),
]
丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清