用tornado写一个博客(2)模板与请求

2015-10-16 11:57:25

本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议

在上一次的博文中,我们使用 tornado 做后台,在前端书写了 Hello Tornado ,但是如果说所有的后台都这么麻烦单调,那么要做一个网站的后台要做的工作就实在太多了,所幸, tornado 和其他框架一样,是支持 python的 template 的,好话不多说我们上代码

模板


tornado 提供一种类似python的语言,可以对前端的html进行 “渲染”,就如同我在之前的博文里面讲的,python大家族都是mtv模式的,而这个 template的功能就由 RequestHandler.render 提供,我们来用用就知道他有多好了

首先,在文件下创建一个html文件, 命名为 index.html:

<!DOCTYPE html>
<html>
<head>
<title>AljunBlogTutorial</title>
</head>
<body>
<h1 style="color: #AD5A5A;" align="center">this is a new blog page based on Tornado!</h1>
</body>
</html>

可见,这是一个很简单的html代码,打出一个 this is a new blog page based on Tornado! 的句子在浏览器上。

在文件下创建 tornado 主文件 temp_req.py,然后写上:

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

port=3000

class PageHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html")

def init_app():
    print "app is running on http://127.0.0.1:%s" % port
    return tornado.web.Application([
        tornado.web.url(r"/",PageHandler),
    ])

if __name__=="__main__":
    app=init_app()
    app.listen(port)
    tornado.ioloop.IOLoop.current().start()
  • 首先,我们还是先import我们需要的 tornado 的组成模块

  • 我们定义一个端口常量,这里是因为这是个小文件这样设计,若是做成一个大的项目,我们会自己在一个文件里把config配置设置好

  • 这里我们写了一个 PageHandler ,用来做请求的处理器,在这里我们继承了 tornado.web.RequestHandler类,他提供了一个 render 方法,会在同层文件寻找里面的字符串参数为名字的文件,然后发给前端,这里我们让他发送 index.html

  • 注意,这里我们书写了一个 init_app 函数,用来初始化我们的app的路由,使用 tornado.web 提供的 url方法,前面是他的路径的正则表达式,后面是,当访问这个路径,将使用的处理器类,这里我们把 /路径的处理交给了 PageHandler,当使用时,顺便在终端打出一段帮助文字

  • 最后是app的启动,让他监听我们之前设置的 port

好了,这时我们在终端输入:

python temp_req.py

便会在终端得到:

app is running on http://127.0.0.1:3000

这时,打开浏览器网址为 http://127.0.0.1:3000 便会看到

pic

这样,我们便能自己写静态的html文件,通过 tornado打到前端的浏览器上了,是不是非常简单

用tornado的模板语言


但上面,还远没有把 tornado的模板的强大功能发挥出来,现在我们便要挑战 tornado的强大功能:

在同文件下创建一个html文件,命名为 list.html,并这样书写:

<!DOCTYPE html>
<html>
<head>
    <title>book list</title>
</head>
<body>
<h2 style="color: #AD5A5A">book list</h2>
<ul>
{% for item in items %}
    <li>{{ item }}</li>
{% end %}
<ul>
</body>
</html>

然后在 temp_req.py里这样增加一个 Handler:

```

class ListHandler(tornado.web.RequestHandler):
    def get(self):
        book_list=['R in action','learning python','django book','guide to tornado','Introduction to Algorithms']
        self.render("list.html",items=book_list)

```

并且修改我们的 app_init:

def init_app():
    print "app is running on http://127.0.0.1:%s" % port
    return tornado.web.Application([
        tornado.web.url(r"/",PageHandler),
        tornado.web.url("/list",ListHandler),
    ])

这样,我们输入:

python temp_req.py

打开 http://127.0.0.1:3000/list就可以看到:

pic

  • 可以看到我们现在 handler 里面定义了一个可迭代的list元素 book_list ,然后把它当作参数给了render函数

  • 接着我们在html文件里面,有一串用 { }包围的代码,其实,在python圈子里面的template,通常认为 {%%}包围的就是python语句,例如 {% for ... %} {% if ... %},但是有两点要记住,就是语句 % 后面要空格,然后没一个这样的python语句后一定要写上 {% end %}来结束它

  • 而在 {{ }}包围的是用来输出变量的值的,如上面的 {{ item }},就把传过来的值打到了前端

  • 其实template并不一定要使用 tornado的,在python界好的模板引擎还是很多的,如 jinja2mako以及饱经诟病的 django.template,这些模板也都够强大,甚至可以书写函数,变量计算等等,用起来很方便

请求


首先我们得清楚,http请求里面有很多种请求形式,例如 getpostputdelete 等等,通常用的最多的是 getpost,get是访问的默认形式,即你打开一个网页就对其进行了一次访问,而post多用来对传输文件。

关于这个请求,请参见我之前的这篇博文 从零到独自开发一个网站(后端)

好了我们来写我们的程序把

用tornado处理get,post请求


这次我们还是使用之前的程序

首先在同文件下新建一个 get_form.html ,并书写:

<!DOCTYPE html>
<html>
<head>
    <title>get form</title>
</head>
<body>
<h1 style="color: #AD5A5A">your data:</h1>
<form method="get" action="show">
    <p>your name:</p>
    <input type="text" name="name">
    <p>your age:</p>
    <input type="text" name="age">
    <p>your subject:</p>
    <input type="text" name="subject">
    <p></p>
    <input type="submit" value="submit">
</form>
</body>
</html>

然后再在同文件下新建一个 show.html ,并书写:

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
{% if flag %}

<h1 style="color:AD5A5A">your personal data:</h1>
<h2 style="color:#ADADAD ">get method</h1>
<p>your name:{{ name }}</p>
<p>your age:{{ age }}</p>
<p>your subject:{{ subject }}</p>

{% else %}

<h1 style="color: #F75000">the result you want</h1>
<h2 style="color:#ADADAD">post method</h2>
<p>{{ result }}</p>

{% end %}

</body>
</html>

好了,我们再写一个 post_form.html文件:

<!DOCTYPE html>
<html>
<head>
    <title>post form</title>
</head>
<body>
<h2 style="color: #F75000">input your score and check if you can go to the stanford</h2>
<form action="/show" method="post">
    <p>your score:</p>
    <input type="text" name="score">
    <p></p>
    <input type="submit" value="submit">
</form>
</form>
</body>
</html>

好了这回我们来书写我们的 temp_req.py文件吧:

增加三个 handler

...
class GetDataHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("get_form.html")

class PostDataHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("post_form.html")

class ResultShowHandler(tornado.web.RequestHandler):

    def get(self):
        name=self.get_argument("name")
        age=self.get_argument("age")
        subject=self.get_argument("subject")
        flag=True
        self.render("show.html",name=name,age=age,subject=subject,flag=flag)
    def post(self):
        stanford_score=1800
        score=int(self.get_argument("score"))
        if score>stanford_score:
            result="you can go to stanford!"
        else:
            result="please choose other college!"
        flag=False
        self.render("show.html",result=result,flag=flag)
...

然后我们改写我们的 init_app:

def init_app():
    print "app is running on http://127.0.0.1:%s" % port
    return tornado.web.Application([
        tornado.web.url(r"/",PageHandler),
        tornado.web.url("/list",ListHandler),
        tornado.web.url("/get",GetDataHandler),
        tornado.web.url("/post",PostDataHandler),
        tornado.web.url("/show",ResultShowHandler),
    ])

好了,我们的程序算是写好了,这回运行

python temp_req.py

打开浏览器,输入网址: http://127.0.0.1:3000/get

便会看到:

pic

接着,我们在这个表单里面输入:

pic

然后点击 submit,便会得到:

pic

好了,这时候我们打开 http://127.0.0.1:3000/post, 便会看到:

pic

然后我们输入一个分数2000:

pic

其实我们在后台设置了,如果分数超过了1800,就可以了,所以点击 submit 后结果是:

pic

好了,我们来逐步地解释这些个步骤吧,

  • 首先,我们先写了一个表单html get_form.html,注意里面的form的 methodget方法,并且我们把 action 设置成了 /show,意思是说,这些在这个表单输入的数据,最后会传像 /show路径,这里有点基础的东西,所有的表单里面的input的数据都要写一个 name,不然后台会无法分辨传过来的参数,例如我们这里设置的name就包括 name,age,subject 所以后台将会得到这三个数据

  • 接着,我们写了一个 show.html用来展示我们的结果,注意这里我们设置了一个 flag ,因为我想让get和post传的数据都在这里展示,如果 methodget 的话,flag为1,如果是 post,flag就为0,

  • 然后,我们写了一个 post_form.html,这里除了 methodpost,其他和 那个get的没什么区别

  • 其实 tornado.RequestHandler里面定义了get和post的不同,会对这两种不同的请求做不同的处理,只需在集成了 RequestHandler的类里面写上 post 函数和 get 函数就表达了不同的处理,我们可以看到我们的 ResultShowHandler类,里面有两个类,就表达了我们对传过来的两种请求的不同的表达,我们可以看到,每次我们 submit后的路径都是 /show,但是打出来的结果却是不一样的,就是我们在这里设置的。

  • 这里顺便一说,用 get_argument得到的数据都是 string类型的,如果需要进行操作,需要进行类型转换

  • 通常 get传一些无关紧要的参数,因为 get参数是可见的,所以如果传来一些密码什么的就会有安全危险,而 post则是加密的,另外,get传的数据是有大小限制的,所以如果是要传图片或者文件什么的,通常使用的都是 post

这样我们便可以使用tornado来进行网页处理了,是不是很自如,很大的网站都可以尝试了,

同样的这次的源代码在这里:

https://github.com/salamer/tornado_blog

tornado 返回首页

Designed and built with all the love in the world by the Mr.ALJUN.

@SERVER BY NGINX AND POWER BY DIGITALOCEAN.

© COPYRIGHT BY GAGASALAMER 2015