Python框架之Django学习笔记(十五)
表单
从Google的简朴的单个搜索框,到常见的Blog评论提交表单,再到复杂的自定义数据输入接口,HTML表单一直是交互性网站的支柱。本次内容将介绍如何用Django对用户通过表单提交的数据进行访问、有效性检查以及其它处理。 与此同时,我们将介绍HttpRequest对象和Form对象。
从Request对象中获取数据
在前面讲述View的函数时已经介绍过HttpRequest对象了,但当时并没有讲太多。 让我们回忆下:每个view函数的第一个参数是一个HttpRequest对象,就像下面这个hello()函数:
from django.http import HttpResponse def hello(request):
return HttpResponse("Hello world")
HttpRequest对象,比如上面代码里的request变量,会有一些有趣的、你必须让自己熟悉这些属性和方法,以便知道能拿它们来做些什么。 在view函数的执行过程中,你可以用这些属性来获取当前request的一些信息(比如,你正在加载这个页面的用户是谁,或者用的是什么浏览器)。
URL相关信息
HttpRequest对象包含当前请求URL的一些信息:

在view函数里,要始终用这个属性或方法来得到URL,而不要手动输入。 这会使得代码更加灵活,以便在其它地方重用。 下面是一个简单的例子:
# BAD!
def current_url_view_bad(request):
return HttpResponse("Welcome to the page at /current/") # GOOD
def current_url_view_good(request):
return HttpResponse("Welcome to the page at %s" % request.path)
提交的数据信息
除了基本的元数据,HttpRequest对象还有两个属性包含了用户所提交的信息: request.GET 和 request.POST。二者都是类字典对象,你可以通过它们来访问GET和POST数据。
类字典对象
我们说“request.GET和request.POST是类字典对象”,意思是他们的行为像Python里标准的字典对象,但在技术底层上他们不是标准字典对象。 比如说,request.GET和request.POST都有get()、keys()和values()方法,你可以用用 for key in request.GET 获取所有的键。
那到底有什么区别呢? 因为request.GET和request.POST拥有一些普通的字典对象所没有的方法。 我们会稍后讲到。
你可能以前遇到过相似的名字:类文件对象,这些Python对象有一些基本的方法,如read(),用来做真正的Python文件对象的代用品。
POST数据是来自HTML中的〈form〉标签提交的,而GET数据可能来自〈form〉提交也可能是URL中的查询字符串(the query string)。
一个简单的表单处理示例
通常,表单开发分为两个部分: 前端HTML页面用户接口和后台view函数对所提交数据的处理过程。 第一部分很简单;现在我们来建立个view来显示一个搜索表单:
from django.shortcuts import render_to_response def search_form(request):
return render_to_response('search_form.html')
这个view函数可以放到Python的搜索路径的任何位置。 为了便于讨论,咱们将它放在 books/views.py 里。
这个 search_form.html 模板,可能看起来是这样的:
<html>
<head>
<title>Search</title>
</head>
<body>
<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="Search">
</form>
</body>
</html>
而 urls.py 中的 URLpattern 可能是这样的:
from mysite.books import views
urlpatterns = patterns('',
# ...
(r'^search-form/$', views.search_form),
# ...
)
PS:我们直接将views模块import进来了,而不是用类似 from mysite.views import search_form 这样的语句,因为前者看起来更简洁。
现在,如果你运行 runserver 命令,然后访问http://127.0.0.1:8000/search-form/,你会看到搜索界面。 非常简单。
不过,当你通过这个form提交数据时,你会得到一个Django 404错误。 这个Form指向的URL /search/ 还没有被实现。 让我们添加第二个视图函数并设置URL:
# urls.py
urlpatterns = patterns('',
# ...
(r'^search-form/$', views.search_form),
(r'^search/$', views.search),
# ...
)
# views.py
def search(request):
if 'q' in request.GET:
message = 'You searched for: %r' % request.GET['q']
else:
message = 'You submitted an empty form.'
return HttpResponse(message)
暂时先只显示用户搜索的字词,以确定搜索数据被正确地提交给了Django,这样你就会知道搜索数据是如何在这个系统中传递的。 简而言之:
- 在HTML里我们定义了一个变量q。当提交表单时,变量q的值通过GET(method=”get”)附加在URL /search/上。
- 处理/search/(search())的视图通过request.GET来获取q的值。
需要注意的是在这里明确地判断q是否包含在request.GET中。就像上面request.META小节里面提到,对于用户提交过来的数据,甚至是正确的数据,都需要进行过滤。 在这里若没有进行检测,那么用户提交一个空的表单将引发KeyError异常:
# BAD!
def bad_search(request):
# The following line will raise KeyError if 'q' hasn't
# been submitted!
message = 'You searched for: %r' % request.GET['q']
return HttpResponse(message)
查询字符串参数
因为使用GET方法的数据是通过查询字符串的方式传递的(例如/search/?q=django),所以我们可以使用requet.GET来获取这些数据。 前面介绍Django的URLconf系统时我们比较了Django的简洁的URL与PHP/Java传统的URL,通过刚才的介绍,我们知道在视图里可以使用request.GET来获取传统URL里的查询字符串(例如hours=3)。
获取使用POST方法的数据与GET的相似,只是使用request.POST代替了request.GET。那么,POST与GET之间有什么不同?当我们提交表单仅仅需要获取数据时就可以用GET; 而当我们提交表单时需要更改服务器数据的状态,或者说发送e-mail,或者其他不仅仅是获取并显示数据的时候就使用POST。 在这个搜索书籍的例子里,我们使用GET,因为这个查询不会更改服务器数据的状态。(如果你有兴趣了解更多关于GET和POST的知识,可以参见http://www.w3.org/2001/tag/doc/whenToUseGet.html。)
既然已经确认用户所提交的数据是有效的,那么接下来就可以从数据库中查询这个有效的数据(同样,在views.py里操作):
from django.http import HttpResponse
from django.shortcuts import render_to_response
from mysite.books.models import Book def search(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
books = Book.objects.filter(title__icontains=q)
return render_to_response('search_results.html',
{'books': books, 'query': q})
else:
return HttpResponse('Please submit a search term.')
让我们来分析一下上面的代码:
- 除了检查q是否存在于request.GET之外,我们还检查来reuqest.GET[‘q’]的值是否为空。
- 我们使用Book.objects.filter(title__icontains=q)获取数据库中标题包含q的书籍。 icontains是一个查询关键字。这个语句可以理解为获取标题里包含q的书籍,不区分大小写。
- 这是实现书籍查询的一个很简单的方法。 我们不推荐在一个包含大量产品的数据库中使用icontains查询,因为那会很慢。
- 最后,我们给模板传递来books,一个包含Book对象的列表。 查询结果的显示模板search_results.html如下所示:
<p>You searched for: <strong>{{ query }}</strong></p>
{% if books %}
<p>Found {{ books|length }} book{{ books|pluralize }}.</p>
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>
{% else %}
<p>No books matched your search criteria.</p>
{% endif %}
注意这里pluralize的使用,这个过滤器在适当的时候会输出s。
以上就是这次的学习内容~
Python框架之Django学习笔记(十五)的更多相关文章
- Python框架之Django学习笔记(五)
第一个Django网页小结 进来的请求转入/hello/. Django通过在ROOT_URLCONF配置来决定根URLconf. Django在URLconf中的所有URL模式中,查找第一个匹配/h ...
- Python框架之Django学习笔记(十七)
Django框架之表单(续二) 今天的这篇博客将是Django学习笔记博客的最后一篇,基本每周最少一篇的Django框架学习,坚持到今天也实属不易,当然了,这个框架的学习仅仅是Django框架的基础部 ...
- Python框架之Django学习笔记(十一)
话说上次说到数据库的基本访问,而数据库我们主要进行的操作就是CRUD,也即是做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete),俗 ...
- Python框架之Django学习笔记(十二)
Django站点管理 十一转眼结束,说好的充电没能顺利开展,反而悠闲的看了电视剧以及去影院看了新上映的<心花路放>.<亲爱的>以及<黄金时代>,说好的劳逸结合现在回 ...
- Python框架之Django学习笔记(十)
又是一周周末,如约学习Django框架.在上一次,介绍了MVC开发模式以及Django自己的MVT开发模式,此次,就从数据处理层Model谈起. 数据库配置 首先,我们需要做些初始配置:我们需要告诉D ...
- Python框架之Django学习笔记(十六)
Django框架之表单(续) 今天简直无力吐槽了,去了香山,结果和网上看到的简直是天壤之别啊,说好的香山的枫树呢?说好的香山的红叶呢?说好的漫山遍野一片红呢?本以为在山上,一口气爬上去,沿路基本都是翠 ...
- Python框架之Django学习笔记(十四)
Django站点管理(续·完) 本想昨天更新的,谁曾想昨天竟然是工作日!我就不吐槽昨天加班到十一点多了,需求增加无疑让我等蛋疼不已,忽而想起一首打油诗: 明月几时有,把酒问群友.不知这次版本,今晚能出 ...
- Python框架之Django学习笔记(六)
模板 上篇博文学习了动态视图,但是,视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python 代码之中. def current_datetime(request): now = ...
- Python框架之Django学习笔记(九)
模型 之前,我们用 Django 建造网站的基本途径: 建立视图和 URLConf . 正如我们所阐述的,视图负责处理一些主观逻辑,然后返回响应结果. 作为例子之一,我们的主观逻辑是要计算当前的日期和 ...
随机推荐
- RxJava2 中多种取消订阅 dispose 的方法梳理( 源码分析 )
Github 相关代码: Github地址 一直感觉 RxJava2 的取消订阅有点混乱, 这样也能取消, 那样也能取消, 没能系统起来的感觉就像掉进了盘丝洞, 迷乱… 下面说说这几种情况 几种取消的 ...
- C++ 宏定义的简单使用
1.定义常量 #define ARRMAX 50 int arr[ARRMAX]; (这种做法不如直接用const来直接定义常量.) 2.代替模板函数或者内联函数,将函数定义成宏.执行效率很快 #de ...
- JAVA 与 sqlite3 连接
SQLite SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中.它是D.RichardHipp建立的公有领域项目.它的设计目标是嵌入式的,而且目前已经 ...
- Linux让Apache支持中文URL图片/文件名
需要用到iconv_hook和mod_encoding Apache(32位): 安装环境:CentOS 5.6 + Apache 2.2.15 (Apache2.4同样适用) 安装结果:安装后支持“ ...
- 用户在设置密码时,提醒请输入半角字符(vue+element+valid)
要保证callback()只有一个出口 rules:{ newPassword: [{validator:(rule,newPassword,callback)=>{ var all = fal ...
- 自动释放池的前世今生 ---- 深入解析 autoreleasepool
http://draveness.me/autoreleasepool.html 关注仓库,及时获得更新:iOS-Source-Code-Analyze Follow: Draveness · Git ...
- 【BZOJ1029】[JSOI2007] 建筑抢修(堆优化贪心)
点此看题面 大致题意: 有N个受到严重损伤的建筑,对于每个建筑,修好它需要\(T1\)秒,且必须在\(T2\)秒之前修完(\(T1\)与\(T2\)不是固定值),问你最多能修好几个建筑. 题解 一看到 ...
- 漫谈 Clustering (5): Hierarchical Clustering
系列不小心又拖了好久,其实正儿八经的 blog 也好久没有写了,因为比较忙嘛,不过觉得 Hierarchical Clustering 这个话题我能说的东西应该不多,所以还是先写了吧(我准备这次一个公 ...
- vue动画使用javascript钩子函数
钩子函数从before-enter – enter –after-enter-entercancelled也是一个完整的生命周期 <transition v-on:before-enter= ...
- IBM MQ Explore使用
一,版本说明: 系统:win10.MQ:V9.04 二.关于帮助文档: 1.读了差不多一大半,个人感觉说明的比较生僻,应该是直译过来的.但是还是可以从这里面学一下基本的操作. 2.对于一些基本的操作, ...