[零基础学python]探析get和post方法

"Do not store up for yourselves treasures on earth, where moth and rust consume and where thieves break in and steal; but store up for yourselves treasures in heaven, where neither moth and rust consumes and where thieves do not break in and steal. For where your treasure is, there your heart will be also." (MATTHEW6:19-21)python

在开发网站的过程当中,post和get是常见经常使用的两个方法,关于这两个方法的详细解释,请列为阅读这篇文章:《HTTP POST GET 本质区别详解》,这篇文章前面已经推荐阅读了,能够这么说,若是看官没有搞明白get和post,也能够写出web程序,可是,只要遇到“可是”,就说明另有乾坤,可是若是看官要对这方面有深刻理解,而且未来能上一个档次,是必须了解的。这就如同你要练习辟邪剑谱中的剑法,不自宫,也能够练,可是没法突破某个极限,岳不群也不傻,最终他要成为超一流,就不惜按照剑谱中开篇所说“欲练神功,挥刀自宫”,“神功”是须要“自宫”为前提,不然,练出来的不是“神功”,没法问鼎江湖。git

特别提醒,看官不要自宫,由于本教程不是辟邪剑谱,也不是葵花宝典,撰写本课程的人更是生理健全者。若看官自宫了,责任自负,与本做者无关。直到目前,科学上还没有有证明或证伪自宫和写程序之间是否存在某种因果关系。因此提醒看官慎重行事。github

仍是扯回来,看下面的代码先:web

#!/usr/bin/env python
#coding:utf-8

import textwrap

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8000, help="Please send email to me", type=int)

class ReverseHandler(tornado.web.RequestHandler):
    def get(self, input_word):
        self.write(input_word[::-1])

class WrapHandler(tornado.web.RequestHandler):
    def post(self):
        text = self.get_argument("text")
        width = self.get_argument("width", 40)
        self.write(textwrap.fill(text, width))

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
        handlers = [
            (r"/reverse/(\w+)", ReverseHandler),
            (r"/wrap", WrapHandler)
        ]
    )
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

这段代码跟上一讲的代码相比,基本结构是同样的,可是在程序主体中,此次写了两个类ReverseHandlerWrapHandler,这两个类中分别有两个方法get()和post()。在tornado.web.Application()实例化中,handlers的参数值分别设置了不一样路径对应这两个类。正则表达式

其它方面跟上一讲的代码同样。编程

把上述代码的文件,存到某个目录下,我给他取名为:request_url.py,名字看官也能够本身定。而后进入该目录,运行:python request_url.py,就将这个tornado框架的网站以端口8000发布了。浏览器

打开网页,在浏览器中输入:http://localhost:8000/reverse/qiwsirpython服务器

界面上输出什么结果?网络

还能够在命令终端,用下面方式调试,跟在网页上输出是等同效果。架构

qw@qw-Latitude-E4300:~$ curl http://localhost:8000/reverse/qiwsirpython
nohtypriswiq

再看另一个路径,看官运行的是不是下面的结果呢?

qw@qw-Latitude-E4300:~$ curl http://localhost:8000/wrap -d text=I+love+Python+programming+and+I+am+writing+python+lessons+on+line
I love Python programming and I am
writing python lessons on line

调试经过,就开始分析其中的奥妙。

get()

在ReverseHandler类中,定义了这个方法。

class ReverseHandler(tornado.web.RequestHandler):
    def get(self, input_word):
        self.write(input_word[::-1])

这个get()方法要和下面Application实例化中的路径:

(r"/reverse/(\w+)", ReverseHandler),

关联起来看。

首先看路径设置:r"/reverse/(\w+)",这个路径的意思就是能够在浏览器的url中输入:http://localhost:8000/reverse/dddd,这个样子的地址,注意路径中的(\w+),是正则表达式,在reverse/的后面能够输入一个或者多个包括下划线的任何单词字符。也就是dddd能够更换为任何其它字母或者下划线,一个或者多个都可以。

在URL中输入的这个地址,就被ReverseHandler类中的get()方法接收,这就是(r"/reverse/(\w+)", ReverseHandler)之含义了。那么,ReverseHandler中的get()方法如何接收url中传递过来的信息呢?

前文已经说过,在def get(self, input_word)中,self参数在类实例化后对应的是tornado.web.RequestHandler,另一个参数input_word用来接收来自url的信息,可是它只接收所设置的路径尾部数据,也就是路径r"/reverse/(\w+)"中reverse后面的第一个分割符号“/”以后的内容,都被input_word接收过来,即正则表达式的内容。

input_word接收过来的对象,是什么类型呢?猜想一下,从前面程序的运行结果看,确定是某种序列类型的对象。具体是哪一种呢?能够实验。

将get方法修改成:

def get(self, input_word):
    input_type = type(input_word)
    self.write("%s"%input_type)

再运行程序,打印出来的是:

qw@qw-Latitude-E4300:~$ curl http://localhost:8000/reverse/qiwei
<type 'unicode'>

这说明,get()方法经过URL接收到的数据类型是unicode编码的字符,即字符串。

原来类方法中的self.write(input_word[::-1])含义是,将原来的字符串倒置,并返回该数据到客户端(如页面)。

>>> a = "python,laoqi"
>>> a[::-1]
'iqoal,nohtyp'
>>> b = [1,2,3,4]
>>> b[::-1]
[4, 3, 2, 1]
>>> c = ("a","b","c")
>>> c[::-1]
('c', 'b', 'a')

这是一种将序列类型对象倒置的一种方法。

总结一下:get()经过第二个参数,得到已经设置的显示路径中最后一个/后面的数据,而且为unincode编码的字符。

这种方式经过URL获得有关数据,也就是说在URL中,只须要以http://localhost/aaa/bbb/ccc的形式来显示路径便可。看官是否注意到,有的网站是这么显示的:http://localhost/aaa?name=Tom&&?age=25,这实际上是两种不一样的规范也好、方法也罢的东西,前者更接近时下流行的REST规范,可能看官据说过MVC吧,我听很多的公司都强调网站要符合MVC规范,却不知,更流行的是REST了。那么到底那个好呢?个人观点:It depends.若是有兴趣,请阅读:《理解本真的REST架构风格》,对REST了解一二。

post()方法

post()也是web上经常使用的方法,在本例中,该方法写在了WrapHandler类中:

class WrapHandler(tornado.web.RequestHandler):
    def post(self):
        text = self.get_argument("text")
        width = self.get_argument("width", 40)
        self.write(textwrap.fill(text, width))

对应的Application类路径:

(r"/wrap", WrapHandler)

可是,看官要注意,post()没法从URL中得到数据。这是跟get()方法很是不同的。关于get和post之间的区别,请看官点击《HTTP POST GET 本质区别详解》阅读。

客户端的数据经过post方法发送到服务器,这个内在过程就是由所谓HTTP协议完成,不用去管它,由于如今咱们只是研究应用层,不去深刻网络协议的层面。看官能够有这样的觉得:怎么传的数据,可是我也能够不讲,就算我也不会吧。不过,若是看官非要了解,请问google大神。

我要解释的是,post()方法怎么接收到客户端传过来的数据。

由于post不能从URL中获得数据,因此就不能用相似的方式在网页的url中输入要传给它的数据了,只能这样来测试:

qw@qw-Latitude-E4300:~$ curl http://localhost:8000/wrap -d text=I+love+Python+programming+and+I+am+writing+python+lessons+on+line
I love Python programming and I am
writing python lessons on line

请看官注意,URL依然是http://localhost:8000/wrap,后面的部分-d text=...,就是向这个地址对应的类WrapHandler中的post方法传送相应的数据,这个数据被tornado.web.RequestHandler中的get_arugment()方法得到,也就是经过text=self.get_argument("text")获得传过来的对象,并赋值给text。

这里须要提醒看官注意,self.get_argument("text")的参数中,是"text",就意味着,传入数据的时候,须要用text这个变量,即必须写成text=...。若是self.get_argument("word"),那么就应该是word=...方式传入数据了。

看官此时是否已经晓得,get_argument()在post方法中,可以得到客户端传过来的数据,固然是unicode编码的。获得这个数据以后,就能够按照本身的须要进行操做了。

下一句width = self.get_argumen("width", 40)是要返回一个对象,这个对象约定变量为40,并将它用在下面的textwrap.fill(text, width)中。这里并无什么特别支出,也能够写成width = 40,其实就是给textwrap.fill()提供参数罢了。关于textwrap模块中的fill方法,能够用help命令来看看。

>>> import textwrap
>>> help(textwrap.fill)

Help on function fill in module textwrap:

fill(text, width=70, **kwargs)
    Fill a single paragraph of text, returning a new string.

    Reformat the single paragraph in 'text' to fit in lines of no more
    than 'width' columns, and return a new string containing the entire
    wrapped paragraph.  As with wrap(), tabs are expanded and other
    whitespace characters converted to space.  See TextWrapper class for
    available keyword args to customize wrapping behaviour.

简要总结RequestHandler

RequestHandler就是请求处理程序的方法,从上面的流程中,能够简要地初步地认为(深奥的东西还很多,这里只能是简要地初步地肤浅地,随着学习的深刻会一点点深刻地):

  • 经过self.write()向客户端返回数据
  • get()中,以一个参数从URL路径末尾获取数据,特别提醒看官,这是在本讲的例子中,get()方法中,用第二个参数得到url数据。在上一讲中,一样是get()方法,用到了greeting = self.get_argument('greeting', 'Hello'),因而不须要在get()中另外写参数,只须要经过"greeting"就能够获得URL中的数据,不过这时候的url应该写成http://localhost:8000/?greeting=PYTHON的样式,因而字符传'PYTHON'就可以让get()中的self.get_argument('greeting','Hello')得到,若是没有,就是'Hello'。
  • post()中,以sel.argument("text")的形式获得text为标签提交的数据。

get和post是http中用的最多的方法啦。此外,Tornado也还支持其它的HTTP请求,如:PUT、DELETE、HEAD、OPTIONS。在具体编程的时候,若是看官用到,能够搜索,通常用的很少。

最后交代一句,get和post方法,因为一个是经过URL获得数据,另一个不是,因此,他们能够写到同一个类中,彼此互不干扰。

还要说明,我在这部分参考了一本书的讲授内容,特别是其中的代码例子,这本书就是《Introduction to Tornado》


本博客在编写过程当中,不免有错误,幸好有广大网友大神们指出。可是因为各类缘由,我在www.itdiffer.com更新比较及时,由于是托管在github上的。在这里通常不进行更新修改。请谅解。

相关文章
相关标签/搜索