zoukankan      html  css  js  c++  java
  • frist Django app — 四、 完善View

    上一篇已经完成了polls的基本功能,接下来完善剩下的vote功能和并使用generic views改进请求处理view。包含表单的简单运用和前后台参数传递。

    目录

    • vote:完善投票功能
    • generic views:改进views.py

    vote

    编辑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>
    • 添加了form表单,使用post提交,提交到的地址是polls:vote代表一个地址,比如:http://127.0.0.1:8000/polls/4/vote/.
    • 这里涉及到了表单提交,添加{% csrf_token %}防止csrf攻击,原理就是每次使用的token不一致,导致无法进行伪造请求,从而防止。
    • forloop.counter是for循环的计数器。

    编辑views.py添加投票功能,注意引入相关的类

    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):
            return render(request, 'polls/detail.html', {
                'question': question,
                'error_message':"you did`t select choice.",
            })
        else:
            selected_choice.votes += 1
            selected_choice.save()
            return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
    request.POST['choice']从post请求里面获取前台传递过来的参数,request.POST 是一个dictionary,键是参数名,值是参数值,档案如果是get请求的话就是request.GET
    return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))在投票成功之后将页面进行了重定向,防止用户使用浏览器的回退功能之后重复提交表单

    到现在为止功能已经完成了,可以进行测试了,启动服务器然后测试相关功能

    generic views

    对于很多web app来说,需要展示内容的方式相近,比如:查看某个列表,查看某一个的具体内容等等,为此Django提供了generic views——Django诠释了什么是快速便捷开发!

    使用generic views改写views.py

    from django.shortcuts import render, get_object_or_404
    from django.http import HttpResponse, Http404, HttpResponseRedirect
    from models import Question, Choice
    from django.views import generic
    from django.core.urlresolvers import reverse
    
    # Create your views here.
    class IndexView(generic.ListView):
        template_name = 'polls/index.html'
        context_object_name = 'latest_question_list'
    
        def get_queryset(self):
            return Question.objects.order_by('-publ_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):
        question = get_object_or_404(Question, pk=question_id)
        try:
            selected_choice = question.choice_set.get(pk=request.POST['choice'])
        except (KeyError, Choice.DoesNotExist):
            return render(request, 'polls/detail.html', {
                'question': question,
                'error_message':"you did`t select choice.",
            })
        else:
            selected_choice.votes += 1
            selected_choice.save()
            return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

    我们将index,detail,result都改写了,使用到了ListView和DetailView。

    IndexView复写了get_quesryset方法来实现我们自己的逻辑,设置了模板页面和返回的参数名称

    DetailView设置了展示详细信息所需要的model和模板页面

    既然使用了generic views就需要改写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]+)/detail/$', 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'),
    ]

    为了使用generic views把参数名称改为pk,因为在DetailView里面已经使用了该名称——这就是约定优于配置。

    总结

    整个程序基本写完了,我们回过头来发现,我们自己真正写了的代码真不多,基本都是依赖Django完成的。可见使用Django快速建站还是有道理的。


    完整代码

    http://pan.baidu.com/s/1o8zqGhs

  • 相关阅读:
    C#使用进度条,并用线程模拟真实数据 ProgressBar用法(转)
    装饰者模式(Decorator Pattern)C#版本的
    C# Stream篇(七) -- NetworkStream
    C# Stream篇(六) -- BufferedStream
    C# Stream篇(五) -- MemoryStream
    C# Stream篇(四) -- FileStream
    C# Stream篇(三) -- TextWriter 和 StreamWriter
    C# Stream篇(二) -- TextReader 和StreamReader
    C# Stream篇(—) -- Stream基类
    代理模式(Proxy Pattern)C#版本的
  • 原文地址:https://www.cnblogs.com/sunshine-2015/p/5668399.html
Copyright © 2011-2022 走看看