zoukankan      html  css  js  c++  java
  • 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>

          {% csrf_token %} django为了防止跨站点伪造请求,POST Form 应当在请求中使用{% csrf_token%}标签

          {% 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     question = get_object_or_404(Question, pk=question_id)
    39     return render(request, 'polls/results.html', {'question': question})
    
    

                编辑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 %}

                以上完成了投票功能,最后需要对投票的结果进行展示,新建网页: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>
    
    <a href="{% url 'polls:detail' question.id %}">Vote again?</a>

                启动站点,浏览http://localhost:8000/polls/

                

                   投票完成之后,查询数据:

                   

                 3.view改良

                   首先每张表都有主键,对polls/urls.py的改良就是将<int:question_id>替换成<int:pk>

    from django.urls import path
    
    from . import views
    
    app_name = 'polls'
    urlpatterns = [
        path('', views.IndexView.as_view(), name='index'),
        path('<int:pk>/', views.DetailView.as_view(), name='detail'),
        path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
        path('<int:question_id>/vote/', views.vote, name='vote'),
    ]

                  polls/views.py中原来定义的index,detail,results 换成 Django generic的view 

    
    
     1 from django.shortcuts import get_object_or_404, render
     2 from django.http import HttpResponseRedirect
     3 from django.urls import reverse
     4 from django.views import generic
     5 from django.utils import timezone
     6 
     7 from .models import Choice, Question
     8 
     9 
    10 class IndexView(generic.ListView):
    11     template_name = 'polls/index.html'
    12     context_object_name = 'latest_question_list'
    13 
    14     def get_queryset(self):
    15         """Return the last five published questions."""
    16         return Question.objects.order_by('-pub_date')[:5]
    17 
    18 
    19 class DetailView(generic.DetailView):
    20     model = Question
    21     template_name = 'polls/detail.html'
    22 
    23 
    24 class ResultsView(generic.DetailView):
    25     model = Question
    26     template_name = 'polls/results.html'
    27 
    28 def vote(request, question_id):
    29     question = get_object_or_404(Question, pk=question_id)
    30     try:
    31         selected_choice = question.choice_set.get(pk=request.POST['choice'])
    32     except (KeyError, Choice.DoesNotExist):
    33         # Redisplay the question voting form.
    34         return render(request, 'polls/detail.html', {
    35             'question': question,
    36             'error_message': "You didn't select a choice.",
    37         })
    38     else:
    39         selected_choice.votes += 1
    40         selected_choice.save()
    41         # Always return an HttpResponseRedirect after successfully dealing
    42         # with POST data. This prevents data from being posted twice if a
    43         # user hits the Back button.
    44         return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

                  view vote牵涉到表单提交,数据库的操作,所以没有使用通用view改造

  • 相关阅读:
    HDU Railroad (记忆化)
    HDU 1227 Fast Food
    HDU 3008 Warcraft
    asp vbscript 检测客户端浏览器和操作系统(也可以易于升级到ASP.NET)
    Csharp 讀取大文本文件數據到DataTable中,大批量插入到數據庫中
    csharp 在万年历中计算显示农历日子出错
    csharp create ICS file extension
    CSS DIV Shadow
    DataTable search keyword
    User select fontface/color/size/backgroundColor设置 字体,颜色,大小,背景色兼容主流浏览器
  • 原文地址:https://www.cnblogs.com/andayhou/p/8340994.html
Copyright © 2011-2022 走看看