• 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。

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

    评论
  • 相关阅读:
    Asp.net Json 解析 与 直接用ip访问返回josn
    mysql 时间函数
    Android之TelephonyManager类的使用案例
    android:screenOrientation的说明 固定屏幕显示方向
    在android.app.Application中定义全局变量
    Android开发实例详解之IMF(Android SDK Sample—SoftKeyboard)
    Android InputMethodManager输入法简介
    android ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType)
    VS编译常见错误枚举01
    Visual C++ Samples-------------Code Project
  • 原文地址:https://www.cnblogs.com/voidy/p/4033328.html
Copyright © 2020-2023  润新知