zoukankan      html  css  js  c++  java
  • Django tutorial part4

    writing_first_django_app_part4

    Write a simple form

    点击每个Question进去detail界面,看到的vote我们希望以选择的形式给用户进行选择,然后将结果以表格的形式POST到服务器.

    # polls/templates/polls/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 是表格提交的地址 {% csrf_token %} : django中防止csrd攻击的语句 每个按钮的value是choice.id,名字是chioce,所以post的时候以关键字choice=#的形式 forloop.counter表示for标签进入循环的次数

    现在真正来实现vote类来处理提交的表单:

    # polls/views.py
    
    from django.shortcuts import get_object_or_404, render
    from django.http import HttpResponseRedirect, HttpResponse
    from django.core.urlresolvers import reverse
    
    from polls.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'])
        except (KeyError, Choice.DoesNotExist):
            # Redisplay the question voting form.
            return render(request, 'polls/detail.html', {
                'question': p,
                '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=(p.id,)))
    

    最后的在选择vote提交之后将会进行重定向,url是polls:results,这个语法就是前面用过的作用域加上url名字。前面在urls.py中有url(r'^(?P<question_id>d+)/results/$', views.results, name = 'results'),所以加上args=(p.id,)之后会得到类似这样的url: 'polls/2/results/'

    要重定向到result界面,所以要在view中实现results类来处理:

    # polls/views.py
    
    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})
    

    /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>
    

    这里很简单就是显示question中每个vote和它的结果,点击vote again会再次进入detail界面来选择vote

     

    Use generic views

    使用通用的views可以省去我们自己写view的步骤,我们可以让我们的poll应用使用通用views系统,需要三个步骤:

    • 转化URLconf
    • 删除旧的无用的views
    • 使用新的views基于generic views
    Amend URLconf

    首先修改polls/urls.py:

    from django.conf.urls import patterns, url
    
    from polls import views
    
    urlpatterns = patterns('',
        url(r'^$', views.IndexView.as_view(), name='index'),
        url(r'^(?P<pk>d+)/$', views.DetailView.as_view(), name='detail'),
        url(r'^(?P<pk>d+)/results/$', views.ResultsView.as_view(), name='results'),
        url(r'^(?P<question_id>d+)/vote/$', views.vote, name='vote'),
    )
    

    将原来的question_id变成了pk,因为DetailView view认为从URL中抓取的关键字因该是"pk".

    然后修改polls/view.py,将原来的index,detail,results类删掉,添加:

    from django.views import generic
    
    from polls.models import Choice, Question
    
    
    class 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'
    

    我们使用了两个generic views: ListView, DetailView IndexView类还是使用index.html模板进行渲染,index.html中有参数latest_question_list,所以要对context_object_name进行赋值,说明文本对象的名字。 查看IndexView里面get_queryset的用法如下:

    Get the list of items for this view. This must be an iterable and may be a queryset (in which queryset-specific behavior will be enabled).

    即获取当前view需要的item列表

  • 相关阅读:
    Leetcode Binary Tree Preorder Traversal
    Leetcode Minimum Depth of Binary Tree
    Leetcode 148. Sort List
    Leetcode 61. Rotate List
    Leetcode 86. Partition List
    Leetcode 21. Merge Two Sorted Lists
    Leetcode 143. Reorder List
    J2EE项目应用开发过程中的易错点
    JNDI初认识
    奔腾的代码
  • 原文地址:https://www.cnblogs.com/jolin123/p/4346172.html
Copyright © 2011-2022 走看看