尊重作者的劳动,转载请注明作者及原文地址 http://www.cnblogs.com/txwsqk/p/6514113.html

完全翻译自官方文档 https://docs.djangoproject.com/en/1.10/intro/tutorial04/

本节内容讲表单

让我们更新一下pools/detail.html,添加html表单的展示

  1. <h1>{{ question.question_text }}</h1>
  2.  
  3. {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
  4.  
  5. <form action="{% url 'polls:vote' question.id %}" method="post">
  6. {% csrf_token %}
  7. {% for choice in question.choice_set.all %}
  8. <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
  9. <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
  10. {% endfor %}
  11. <input type="submit" value="Vote" />
  12. </form>

解释一下上面的代码:

form里添加了一个radio单选框,label是单选框的标签,每个单选框的值是 choice.id,当你点了"submit"提交表单时,实际提交的内容是

一个变量choice=choice.id 即 input的name和value,表单提交的方法必须是post

forloop.counte是for循环的一个计数器,表示循环了多少次

{% csrf_token %}  这个是用来防止跨站攻击的,django已经帮我们做好了,放在form上就可以了

提交这个表单时,匹配的url是这个

  1. url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),

现在更新一下我们的vote的视图

  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,)))

解释request.POST 你用post提交表单时传的参数就是用这个接收,是一个字典类型的;对应的request.GET就是接收get请求的参数

  1. request.POST['choice']当key不存在时,会抛一个KeyError异常,所以代码要捕获这个异常
    HttpResponseRedirect(url)当成功提交表单返回结果时就用这个函数
    reverse这个函数是为了避免url的硬编码,本来这个url应该是这样的
  2. url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
    现在呢
  1. reverse('polls:results', args=(question.id,) 看不明白的请去复习上一节的内容(urls.py里的app_nameurl()里的name就是这个用处
  1.  

现在来完成result的视图

  1. from django.shortcuts import get_object_or_404, render
  2.  
  3. def results(request, question_id):
  4. question = get_object_or_404(Question, pk=question_id)
  5. return render(request, 'polls/results.html', {'question': question})

result的视图有了,下面写展示的模板

  1. <h1>{{ question.question_text }}</h1>
  2.  
  3. <ul>
  4. {% for choice in question.choice_set.all %}
  5. <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
  6. {% endfor %}
  7. </ul>
  8.  
  9. <a href="{% url 'polls:detail' question.id %}">Vote again?</a>

这个例子就是你选择单选按钮,然后点击提交按钮,跳转到一个新的页面,没有使用ajax.

注意:

vote视图这里有并发问题,当多个人对同一个question投票时,数据库在存和取时就有资源竞争问题了

django的解决方案在此 https://docs.djangoproject.com/en/1.10/ref/models/expressions/#avoiding-race-conditions-using-f

厉害的来了

通用视图

考虑一下我们前面写的视图detail(),results(),index()都是web开发中最通用的操作,根据url的参数从数据库存取内容,然后模板展示,这就是django通用视图考虑的问题,下面让我们用通用视图修改一下我们前面的应用pools

先修改urls.py

  1. from django.conf.urls import url
  2.  
  3. from . import views
  4.  
  5. app_name = 'polls'
  6. urlpatterns = [
  7. url(r'^$', views.IndexView.as_view(), name='index'),
  8. url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
  9. url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
  10. url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
  11. ]

修改视图views.py

  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.  
  6. from .models import Choice, Question
  7.  
  8. class IndexView(generic.ListView):
  9. template_name = 'polls/index.html'
  10. context_object_name = 'latest_question_list'
  11.  
  12. def get_queryset(self):
  13. """Return the last five published questions."""
  14. return Question.objects.order_by('-pub_date')[:5]
  15.  
  16. class DetailView(generic.DetailView):
  17. model = Question
  18. template_name = 'polls/detail.html'
  19.  
  20. class ResultsView(generic.DetailView):
  21. model = Question
  22. template_name = 'polls/results.html'
  23.  
  24. def vote(request, question_id):
  25. ... # same as above, no changes needed.

这里我们用了两个新的视图ListView和DetailView

ListView 展示成列表

DetailView 根据不同的model展示不同的详情页

这两个视图都需要一个叫model的属性,它得知道根据那个model展示相应的内容

DetailView通用视图是根据url中的的pk参数来获取数据库内容的,所以我们urls.py做了相应修改

这两个通用视图如果你不传template_name那么会使用默认的模板文件

DetailView使用<app name>/<modelname>_detail.html 本应用中就是 "polls/question_detail.html"

ListView使用<app name>/<modelname>_list.html ,当然你传了template_name它就用你定义的模板了

在前面的章节中我们可以给urls.py里定义的url()定义一个context字典来给view()传参数,通用视图有预定义的变量可以使用

DetailView使用model的小写作为context变量的key

ListView使用model的小写+_list作为context的key

当然你想使用自己的context可以传context_object_name来自定义你的context

更多通用视图的内容请参考 https://docs.djangoproject.com/en/1.10/topics/class-based-views/

本节完

django入门-表单-part4的更多相关文章

  1. python运维开发(十九)----Django后台表单验证、session、cookie、model操作

    内容目录: Django后台表单验证 CSRF加密传输 session.cookie model数据库操作 Django后台Form表单验证 Django中Form一般有2种功能: 1.用于做用户提交 ...

  2. django form表单验证

    一. django form表单验证引入 有时时候我们需要使用get,post,put等方式在前台HTML页面提交一些数据到后台处理例 ; <!DOCTYPE html> <html ...

  3. django from表单验证

    django from表单验证   实现:表单验证 工程示例: urls.py 1 2 3 4 5 6 7 8 9 from django.conf.urls import url from djan ...

  4. django Form表单的使用

    Form django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm 关于django的表单系统,主要分两种 基于django.forms.Form ...

  5. Django(5) session登录注销、csrf及中间件自定义、django Form表单验证(非常好用)

    一.Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 数据库(默认) 缓存 文件 缓存+数据库 加密cookie 1.数据库Session 1 2 3 4 5 ...

  6. django创建表单以及表单数据类型和属性

    08.15自我总结 关于django的表单不同关系之间的创建 一.不同关系之间的创建 1.一对一 举例 母表:userinfo id name age 1 张三 12 2 李四 58 字表:priva ...

  7. Django form表单 组件

    目录 Django form表单 组件 Form 组件介绍 普通方式手写注册功能 使用form组件实现注册功能 Form 常用字段与插件 常用字段(必备) 字段参数(必备) 内置验证(必备) 自定义效 ...

  8. [转]django自定义表单提交

    原文网址:http://www.cnblogs.com/retop/p/4677148.html 注:本人使用的Django1.8.3版本进行测试 除了使用Django内置表单,有时往往我们需要自定义 ...

  9. Django实现表单验证、CSRF、cookie和session、缓存、数据库多表操作(双下划綫)

    通常验证用户输入是否合法的话,是前端js和后端共同验证的,这是因为前端js是可以被禁用的,假如被禁用了,那就没法用js实现验证合法与否了,也就是即使用户输入的不合法,但是也没提示,用户也不知道怎么输入 ...

随机推荐

  1. go_goroutine and channel

    协程Coroutine 轻量级”线程“ 非抢占式多任务处理,由协程主动交出控制权(如果程序中间没有print,程序会一直霸占着调度器) 编译器/解释器/虚拟机层面的多任务 多个协程可能在一个或多个线程 ...

  2. 9-eclispe中右键BuildPath没有了

    Eclipse 右上角的代码视图,选择Java就好了!

  3. ASP.NET文件上传大小限制

    上传限制 我们以为的文件大小限制 我们大家都知道ASP.NET为我们提供了文件上传服务器控件FileUpload,默认情况下可上传的最大文件为4M,如果要改变可上传文件大小限制,那么我们可以在web. ...

  4. c语言蛋疼的字符串赋值

    我觉得c语言比较蛋疼的一个地方就是给字符串赋值,不是初始化,是赋值. char string[20]={0}; 你不能通过 string="hello";这种方式赋值.但是在字符串 ...

  5. JavaScript RegExp.test() 方法

    定义和用法: test() 方法用于检测一个字符串是否匹配某个模式. 语法: RegExpObject.test(string); RegExpObject:正则表达式; string:必须参数,要检 ...

  6. Debian 如何使用测试版更新软件包到最新的版本

    #vim /etc/apt/sources.list 将版本代号替换成 testing 然后更新,应可以安装最新的软件包了.

  7. 【转】Defunct进程 僵尸进程

    在测试基于 DirectFB+Gstreamer 的视频联播系统的一个 Demo 的时候,其中大量使用 system 调用的语句,例如在 menu 代码中的 system("./play&q ...

  8. redis windows下安装

    1.下载redis windows文件包 下载地址 2.解压文件包 复制压缩包地址 3.进入cmd 命令行 cd进入redis文件包目录 4.执行 redis-server.exe  使用netsta ...

  9. JAVA反射机制o

    Reflection是Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说"自审",并能直接操作程序的内部属性.例如,使用它能获得 Java 类中 ...

  10. 在TFS 2013中选择一周中的工作日,例如增加星期日

    默认情况下,TFS在迭代视图中不计算周末的工作,如果出现调休的情况,则周末的工作日不会出现在迭代视图中,也不会参与燃尽图的计算.但是可以调整团队一周中的工作日,从而修正迭代计算方式,修改的方式参考下图 ...