Django App(四) Submit a form
Django App(四) Submit a form
经过前面的努力,到这里我们已经基本完成了,从服务器到浏览器的数据下发,还没有解决从浏览器到服务器的数据上传,这一节将创建一个Form获取从浏览器提交的数据
1.新建Form
接着前面建的项目,网上调查,每一个Question有多个Choice,当用户针对特定问题,可以提交选择,数据库记录每个Choice的vote数,所以新建:
polls/templates/detail.html
编写代码如下:
<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>
{% url ‘polls:vote’ question.id %}的写法,是为了防止页面硬编码[查看上一篇内容],引入的url的另一种写法, polls:vote 的写法是给polls/urls.py 加了url命名空间:
1 from django.urls import path 2 from . import views 3 app_name="polls" 4 urlpatterns=[ 5 path('',views.index,name='index'), 6 path('<int:question_id>/detail',views.detail,name="detail"), #定义detail view 7 path('<int:question_id>/results',views.results,name='results'),#定义格式:/参数[参数类型为int]/results 8 #这里将原来的vote/<int:question_id>改成<Vote/<int:question_id> 9 path('vote/<int:question_id>',views.vote,name='vote') #定义格式:vote/参数[参数类型为int] 10 ]
上面建的表单要提交一个question_id 和 Choice_Id 到 /vote view,为了表单提交数据的安全性,这里指定使用POST传输,这点view没有特别要求,改造view/vote 对指定的question_id的choice_id的votes+1
2.接收Form数据并处理业务
修改polls/views.py/vote如下,(为了方便对比这里贴出来整个Views.py):
1 from django.shortcuts import get_object_or_404, render 2 from django.http import HttpResponseRedirect, HttpResponse 3 from django.urls import reverse 4 5 from .models import Choice, Question 6 # ... 7 def vote(request, question_id): 8 question = get_object_or_404(Question, pk=question_id) 9 try: 10 selected_choice = question.choice_set.get(pk=request.POST['choice']) 11 except (KeyError, Choice.DoesNotExist): 12 # Redisplay the question voting form. 13 return render(request, 'polls/detail.html', { 14 'question': question, 15 'error_message': "You didn't select a choice.", 16 }) 17 else: 18 selected_choice.votes += 1 19 selected_choice.save() 20 # Always return an HttpResponseRedirect after successfully dealing 21 # with POST data. This prevents data from being posted twice if a 22 # user hits the Back button. 23 return HttpResponseRedirect(reverse('polls:results', args=(question.id,))) 24 25 def index(request): 26 latest_question_list = Question.objects.order_by('-pub_date')[:5] 27 28 context = { 29 'latest_question_list': latest_question_list, 30 } 31 return render(request,'polls/index.html',context) 32 # ... 33 def detail(request, question_id): 34 question = get_object_or_404(Question, pk=question_id) 35 return render(request, 'polls/detail.html', {'question': question}) 36 37 def results(request, question_id): 38 response = "You're looking at the results of question %s." 39 return HttpResponse(response % question_id)
编辑polls/templates/polls/index.html如下:
{% if latest_question_list %} <ul> {% for question in latest_question_list %} <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
启动站点,浏览http://localhost:8000/polls/
投票完成之后,查询数据: