zoukankan      html  css  js  c++  java
  • Python框架之Django学习笔记(十五)

    表单

      从Google的简朴的单个搜索框,到常见的Blog评论提交表单,再到复杂的自定义数据输入接口,HTML表单一直是交互性网站的支柱。本次内容将介绍如何用Django对用户通过表单提交的数据进行访问、有效性检查以及其它处理。 与此同时,我们将介绍HttpRequest对象和Form对象。

    从Request对象中获取数据

      在前面讲述View的函数时已经介绍过HttpRequest对象了,但当时并没有讲太多。 让我们回忆下:每个view函数的第一个参数是一个HttpRequest对象,就像下面这个hello()函数:

    1 from django.http import HttpResponse
    2 
    3 def hello(request):
    4     return HttpResponse("Hello world")

       HttpRequest对象,比如上面代码里的request变量,会有一些有趣的、你必须让自己熟悉这些属性和方法,以便知道能拿它们来做些什么。 在view函数的执行过程中,你可以用这些属性来获取当前request的一些信息(比如,你正在加载这个页面的用户是谁,或者用的是什么浏览器)。

    URL相关信息

      HttpRequest对象包含当前请求URL的一些信息:

      在view函数里,要始终用这个属性或方法来得到URL,而不要手动输入。 这会使得代码更加灵活,以便在其它地方重用。 下面是一个简单的例子: 

    1 # BAD!
    2 def current_url_view_bad(request):
    3     return HttpResponse("Welcome to the page at /current/")
    4 
    5 # GOOD
    6 def current_url_view_good(request):
    7     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来显示一个搜索表单:

    1 from django.shortcuts import render_to_response
    2 
    3 def search_form(request):
    4     return render_to_response('search_form.html')

      这个view函数可以放到Python的搜索路径的任何位置。 为了便于讨论,咱们将它放在 books/views.py 里。

      这个 search_form.html 模板,可能看起来是这样的:

     1 <html>
     2 <head>
     3     <title>Search</title>
     4 </head>
     5 <body>
     6     <form action="/search/" method="get">
     7         <input type="text" name="q">
     8         <input type="submit" value="Search">
     9     </form>
    10 </body>
    11 </html>

      而 urls.py 中的 URLpattern 可能是这样的:

    1 from mysite.books import views
    2 
    3 urlpatterns = patterns('',
    4     # ...
    5     (r'^search-form/$', views.search_form),
    6     # ...
    7 )

      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:

     1 # urls.py
     2 
     3 urlpatterns = patterns('',
     4     # ...
     5     (r'^search-form/$', views.search_form),
     6     (r'^search/$', views.search),
     7     # ...
     8 )
     9 
    10 # views.py
    11 
    12 def search(request):
    13     if 'q' in request.GET:
    14         message = 'You searched for: %r' % request.GET['q']
    15     else:
    16         message = 'You submitted an empty form.'
    17     return HttpResponse(message)

      暂时先只显示用户搜索的字词,以确定搜索数据被正确地提交给了Django,这样你就会知道搜索数据是如何在这个系统中传递的。 简而言之:

    1. 在HTML里我们定义了一个变量q。当提交表单时,变量q的值通过GET(method=”get”)附加在URL /search/上。
    2. 处理/search/(search())的视图通过request.GET来获取q的值。

      需要注意的是在这里明确地判断q是否包含在request.GET中。就像上面request.META小节里面提到,对于用户提交过来的数据,甚至是正确的数据,都需要进行过滤。 在这里若没有进行检测,那么用户提交一个空的表单将引发KeyError异常: 

    1 # BAD!
    2 def bad_search(request):
    3     # The following line will raise KeyError if 'q' hasn't
    4     # been submitted!
    5     message = 'You searched for: %r' % request.GET['q']
    6     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,因为这个查询不会更改服务器数据的状态。(如果你有兴趣了解更多关于GETPOST的知识,可以参见http://www.w3.org/2001/tag/doc/whenToUseGet.html。)

      既然已经确认用户所提交的数据是有效的,那么接下来就可以从数据库中查询这个有效的数据(同样,在views.py里操作): 

     1 from django.http import HttpResponse
     2 from django.shortcuts import render_to_response
     3 from mysite.books.models import Book
     4 
     5 def search(request):
     6     if 'q' in request.GET and request.GET['q']:
     7         q = request.GET['q']
     8         books = Book.objects.filter(title__icontains=q)
     9         return render_to_response('search_results.html',
    10             {'books': books, 'query': q})
    11     else:
    12         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如下所示:
     1 <p>You searched for: <strong>{{ query }}</strong></p>
     2 
     3 {% if books %}
     4     <p>Found {{ books|length }} book{{ books|pluralize }}.</p>
     5     <ul>
     6         {% for book in books %}
     7         <li>{{ book.title }}</li>
     8         {% endfor %}
     9     </ul>
    10 {% else %}
    11     <p>No books matched your search criteria.</p>
    12 {% endif %}

      注意这里pluralize的使用,这个过滤器在适当的时候会输出s。

      以上就是这次的学习内容~

    评论
  • 相关阅读:
    Proj THUDBFuzz Paper Reading: The Art, Science, and Engineering of Fuzzing: A Survey
    Proj THUDBFuzz Paper Reading: A systematic review of fuzzing based on machine learning techniques
    9.3 付费代理的使用
    11.1 Charles 的使用
    第十一章 APP 的爬取
    10.2 Cookies 池的搭建
    10.1 模拟登录并爬取 GitHub
    11.5 Appium 爬取微信朋友圈
    11.4 Appium 的基本使用
    11.3 mitmdump 爬取 “得到” App 电子书信息
  • 原文地址:https://www.cnblogs.com/voidy/p/4033328.html
Copyright © 2011-2022 走看看