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列表

时间: 2024-10-10 23:18:20

Django tutorial part4的相关文章

Django Tutorial 学习笔记

实际操作了Django入门教程中的范例,对一些细节有了更清晰的掌握.感觉只看文档不动手是不行的,只看文档没法真正掌握其中要素之间的关系,看了很多遍也不行,必须动手做了才能掌握.同时,这次练习在Eclipse+PyDev环境下进行,了解了这个开发环境对Django的支持情况. Django网站提供的入门教程: https://docs.djangoproject.com/en/1.6/intro/tutorial01/ 教程中的数据库结构 Poll {question, pub_date} Cho

django入门-part4

完全翻译自官方文档 https://docs.djangoproject.com/en/1.10/intro/tutorial04/ 本节内容讲表单 让我们更新一下pools/detail.html,添加html表单的展示 <h1>{{ question.question_text }}</h1> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% e

Django tutorial part5

writing_first_django_app_part5 Automated Testing 解决问题一个很好的方法是首先描述这个问题,然后写出代码来实现它.但是很多人习惯先写好代码然后再进行调试找问题.也许在写代码之前先写好一些测试会是更好的选择. A little bug 前面在我们的Question.was_published_recently()函数中有一个小问题,如果它是一天之内创建的则会返回True,但是如果pub_date是未来的时间也会返回True 通常应用的测试会放到tes

Django tutorial part2

writing_first_django_app_part2 Create super user 下面开始创建管理者帐号: $ python manage.py createsuperuser 输入用户名和密码,邮箱之后创建帐号 运行runserver之后,进入http://127.0.0.1:8000/admin/ 可以登录管理界面 登录之后这时在管理界面还没能看到我们的poll应用,我们需要告诉admin我们的Question对象需要在管理界面显示,修改polls/admin.py: fro

Django tutorial part3

writing_first_django_app_part3 在Django中,网页和其他内容都是通过views来呈现的,每个view由一个简单的python函数来表示,django通过检查url来选择一个view URL pattern: URL的简单通用形式, eg: /newsarchive/<year>/<month>/ python用'URLconfs'来将URL patterns匹配到views 先看一个简单view的例子 # polls/view.py from dj

Django tutorial part1

writing_first_django_app_part1 Creating a project 查看django版本: $ python -c "import django; print(django.get_version())" 创建工程,进入需要放置工程的目录: $ django-admin.py startproject mysite 会创建以下文件: mysite/ manage.py mysite/ __init__.py settings.py urls.py wsg

Django tutorial part6

writing_first_django_app_part6 在django中,网页应用中的一些附加文件,如image, JS, CSS等,称为静态文件"static files" django.contrib.staticfiles: 从各个应用中收集静态文件,放到一个单独的位置,方便使用和管理 Using CSS 静态文件查找路径的时候与template类似,首先在polls目录下创建目录static,在里面再创建一个polls目录,在这个polls目录里面才放置静态文件,现在创建

Pyhon + Django 1.7.2 tutorial + virtualenv简单使用

最近换了工作, 进的team项目中大概是个python + django的组合, python本身的语法以及特性撸过一边之后,这两天按着django官方的文档倒腾了几天, 文档非常详细,本人英语水平也就那样,基本没什么压力,建议像我一样的新手直接去看官方文档,首先内容绝对是更新到了最新的版本,内容组织渐进有序,当然咯,就算按照文档一步一步来,倒腾的过程中总归会碰到些问题,这边博文权当给个记个流水账以后能翻翻或者说有更深的理解了顺便来update下,看看自己的一些思考方式,若果顺便也能给其他人带来

Django 1.6 CBVs

Django 1.6 最佳实践: 如何正确使用 CBVs (Class-based views) Class-based views是Django为解决建站过程中的常见的呈现模式而建立的. 在这节中, 我们着重讲一下CBVs的使用技巧和一般原则. 1. CBVs的使用原则 代码越少越好 永远不要重复代码 View应当只包含呈现逻辑, 不应包括业务逻辑 保持view逻辑清晰简单 不要将CBVs用作403, 404, 500的错误处理程序 保持mixin简单明了 2. 如何使用mixin 在编程中m