django入门-表单-part4
尊重作者的劳动,转载请注明作者及原文地址 http://www.cnblogs.com/txwsqk/p/6514113.html
完全翻译自官方文档 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>{% 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里添加了一个radio单选框,label是单选框的标签,每个单选框的值是 choice.id,当你点了"submit"提交表单时,实际提交的内容是
一个变量choice=choice.id 即 input的name和value,表单提交的方法必须是post
forloop.counte是for循环的一个计数器,表示循环了多少次
{% csrf_token %}
这个是用来防止跨站攻击的,django已经帮我们做好了,放在form上就可以了
提交这个表单时,匹配的url是这个
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
现在更新一下我们的vote的视图
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse from .models import Choice, Question
# ...
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):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': question,
'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=(question.id,)))
解释request.POST 你用post提交表单时传的参数就是用这个接收,是一个字典类型的;对应的request.GET就是接收get请求的参数
request.POST['choice']当key不存在时,会抛一个KeyError异常,所以代码要捕获这个异常
HttpResponseRedirect(url)当成功提交表单返回结果时就用这个函数
reverse这个函数是为了避免url的硬编码,本来这个url应该是这样的 url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
现在呢
reverse('polls:results', args=(question.id,) 看不明白的请去复习上一节的内容(urls.py里的app_name和url()里的name就是这个用处
现在来完成result的视图
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})
result的视图有了,下面写展示的模板
<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>
这个例子就是你选择单选按钮,然后点击提交按钮,跳转到一个新的页面,没有使用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
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]+)/$', 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'),
]
修改视图views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import generic from .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' def vote(request, question_id):
... # 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的更多相关文章
- python运维开发(十九)----Django后台表单验证、session、cookie、model操作
内容目录: Django后台表单验证 CSRF加密传输 session.cookie model数据库操作 Django后台Form表单验证 Django中Form一般有2种功能: 1.用于做用户提交 ...
- django form表单验证
一. django form表单验证引入 有时时候我们需要使用get,post,put等方式在前台HTML页面提交一些数据到后台处理例 ; <!DOCTYPE html> <html ...
- django from表单验证
django from表单验证 实现:表单验证 工程示例: urls.py 1 2 3 4 5 6 7 8 9 from django.conf.urls import url from djan ...
- django Form表单的使用
Form django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm 关于django的表单系统,主要分两种 基于django.forms.Form ...
- Django(5) session登录注销、csrf及中间件自定义、django Form表单验证(非常好用)
一.Django中默认支持Session,其内部提供了5种类型的Session供开发者使用: 数据库(默认) 缓存 文件 缓存+数据库 加密cookie 1.数据库Session 1 2 3 4 5 ...
- django创建表单以及表单数据类型和属性
08.15自我总结 关于django的表单不同关系之间的创建 一.不同关系之间的创建 1.一对一 举例 母表:userinfo id name age 1 张三 12 2 李四 58 字表:priva ...
- Django form表单 组件
目录 Django form表单 组件 Form 组件介绍 普通方式手写注册功能 使用form组件实现注册功能 Form 常用字段与插件 常用字段(必备) 字段参数(必备) 内置验证(必备) 自定义效 ...
- [转]django自定义表单提交
原文网址:http://www.cnblogs.com/retop/p/4677148.html 注:本人使用的Django1.8.3版本进行测试 除了使用Django内置表单,有时往往我们需要自定义 ...
- Django实现表单验证、CSRF、cookie和session、缓存、数据库多表操作(双下划綫)
通常验证用户输入是否合法的话,是前端js和后端共同验证的,这是因为前端js是可以被禁用的,假如被禁用了,那就没法用js实现验证合法与否了,也就是即使用户输入的不合法,但是也没提示,用户也不知道怎么输入 ...
随机推荐
- 初步认识session
TestSession01.java protected void doPost(HttpServletRequest request, HttpServletResponse response) t ...
- SO_KEEPALIVE选项
[SO_KEEPALIVE选项 ] 对于面向连接的TCP socket,在实际应用中通常都要检测对端是否处于连接中,连接端口分两种情况: 1.连接正常关闭,调用close() shutdown()连接 ...
- centos7之saltstack安装
查阅来自salt官网:http://docs.saltstack.cn/topics/installation/rhel.html To install using the SaltStack rep ...
- Luogu 4433 [COCI2009-2010#1] ALADIN
LOJ 2958 线段树 + 类欧 主要矛盾就是$\sum\limits_{i = l}^{r}Ai \mod B$怎么做. 拆成前缀和相减的形式,有 $$\sum_{i = 0}^{r}(Ai \m ...
- Android 集成支付宝第三方登录
前言: 在集成支付宝支付的时候遇到一点小麻烦,先在此记录供大家参考 1.授权 支付宝第三方登录需要在后台进行授权,在查看授权的时候我们一定要看清楚时候真的已经获得了权限(我在没有获取权限的情况下集成的 ...
- Net下的 ORM框架介紹(转)
http://www.cnblogs.com/zhaoyx/articles/1896638.html 在.NET平台下,关于数据持久层框架非常多,本文主要对如下几种做简要的介绍并推荐一些学习的资源: ...
- Leader/Follower多线程网络模型介绍
之前分享过<轻量级 web server Tornado代码分析>,介绍了目前我们采用nginx + tornado的方式搭建升级.配管.数据中心等各类服务组建客户端迭代体系.最近注意到, ...
- Template Method Design Pattern in Java
Template Method is a behavioral design pattern and it’s used to create a method stub and deferring s ...
- POJ 3685 Matrix (二分套二分)
Matrix Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 8674 Accepted: 2634 Descriptio ...
- 20145233《网络对抗》Exp9 Web安全基础实践
20145233<网络对抗>Exp9 Web安全基础实践 实验问题思考 SQL注入攻击原理,如何防御? SQL注入攻击就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符 ...