使用Python的Tornado框架实现一个Web端图书展示页面

作者:Kevin_Yang 时间:2022-04-23 07:23:48 

首先,为什么选择Tornado:
1.高性能的网络库,这可以和gevent,twisted,libevent等做对。
提供了异步io支持,超时事件处理,在此基础上提供了tcpserver,httpclient,尤其是curlhttpclient,
在现有http客户端中肯定排第一。可以用来做爬虫,游戏服务器,据我所知业界已有使用tornado作为游戏服务器

2.web框架,这可以和django,flask对。
提供了路由,模板等web框架必备组件。与其他区别是tornado是异步的,天然适合长轮训,
这也是friendfeed发明tornado的原因,当前flask也可以支持,但必须借助gevent等

3.较为完备的http服务器,这点可以和nginx,apache对比,
但只支持http1.0,所以使用nginx做前段不仅是为了更好利用多核,也是让其支持http1.1

4.完备的wsgi服务器,这可以和gunicore,gevent wsgi server做对比,
也就是说可以让flask运行在tornado之上,让tornado加速flask

5.提供了完备的websocket支持,这让html5的游戏等提供了便利。
像知乎长轮训就是使用了websocket,但websocket手机支持的不是很好,
前段时间不得不使用定时ajax发送大量请求,期待手机浏览器赶快奋起直追

使用tornado创建一个简单的图书介绍页
好了,言归正传,下面我们来看一下这个图书介绍页的代码实现:
1.创建一个web服务的入口文件 blockmain.py


#coding:utf-8
import tornado.web
import tornado.httpserver
import tornado.ioloop
import tornado.options
import os.path
import json
import urllib2

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

class MainHandler(tornado.web.RequestHandler):
 def get(self):
   self.render(
     "index.html",
     page_title = "Burt's Books ¦ Home",
     header_text = "Welcome to Burt's Books!",
     books = ['细说php','python','PHP','小时代']
   )

class HelloModule(tornado.web.UIModule):
 def render(self):
   return'<h1>I am yyx and this is an information from module hello!</h1>'

class BookModule(tornado.web.UIModule):
 def render(self,bookname):
   doubanapi = r'https://api.douban.com/v2/book/'
   searchapi = r'https://api.douban.com/v2/book/search?q='
   searchurl = searchapi+bookname
   searchresult = urllib2.urlopen(searchurl).read()
   bookid = json.loads(searchresult)['books'][0]['id']
   bookurl = doubanapi+bookid
   injson = urllib2.urlopen(bookurl).read()
   bookinfo = json.loads(injson)
   return self.render_string('modules/book.html',book = bookinfo)

def embedded_javascript(self):
   return "document.write(\"hi!\")"

def embedded_css(self):
   return '''.book {background-color:#F5F5F5}
        .book_body{color:red}
   '''

def html_body(self):
   return '<script>document.write("Hello!")</script>'

if __name__ == "__main__":
 tornado.options.parse_command_line()
 app = tornado.web.Application(
   handlers = [
     (r'/',MainHandler),

],
   template_path = os.path.join(os.path.dirname(__file__),'templates'),
   static_path = os.path.join(os.path.dirname(__file__),'static'),
   debug = True,
   ui_modules={'Hello':HelloModule,'Book':BookModule}

)
 http_server = tornado.httpserver.HTTPServer(app)
 http_server.listen(options.port)
 tornado.ioloop.IOLoop.instance().start()

说明一下,一些基本的MVC概念:
tornado也是通过pathinfo模式来匹配用户的输入来获得参数,然后再调用相应的处理函数,它是通过为各种匹配模式设定相应的class类来处理,比如我这里就是通过class MainHandler来处理来自/的get请求
MainHandler把请求render渲染到index.html,参数在index.html中通过{{参数}}来调用

2.建立相应的模板,先创建一个基础的父类main.html模板,创建templates目录,在它下面创建main.html,这个模板只是定义了最基础的网页框架,里面的具体内容由继承于它的子类来具体实现


<html>
<head>
 <title>{{ page_title }}</title>
 <link rel="stylesheet" href="{{ static_url("css/style.css") }}" />
</head>
<body>
 <div id="container">
   <header>
     {% block header %}<h1>Burt's Books</h1>{% end %}
   </header>
   <div id="main">
     <div id="content">
       {% block body %}{% end %}
     </div>
   </div>
   <footer>
     {% set mailLink = '<a href="mailto:contact@burtsbooks.com">Contact Us</a>' %}
     {% set script = '<script>alert("hello")</script>' %}
     {% block footer %}

<p>
         For more information about our selection, hours or events, please email us at{% raw mailLink %}

<!-- {% raw script %} 这里将原样输出,也就是会弹一个框-->
       </p>
     {% end %}
   </footer>
 </div>
 <script src="{{ static_url("js/script.js") }}"></script>
 </body>
</html>

这里是定义了一个主框架,其中里面的{% block header %}<h1>Burt's Books</h1>{% end %}是为了子类模板的继承的块(block),当子类继承了这个main.html,具体这个块里写什么内容由子类来实现,不实现的话就使用父类的默认 值,如是这里的<h1>Burt's Books</h1>,MainHandler类是render到一个index.html,那么接下来写一个index.html来继承这 个父类


{% extends "main.html" %}

{% block header %}
 <h1>{{ header_text }}</h1>
{% end %}

{% block body %}
 <div id="hello">
   <p>Welcome to Burt's Books!</p>
   {% module Hello() %}

{% for book in books %}
     {% module Book(book) %}
   {% end %}
   <p>...</p>
 </div>
{% end %}

简单简洁吧,这也是使用了继承的好处,不用再重复写父类的东西,只要实现父类的block内容即可
MainHandler类里的render方法中的参数


page_title = "Burt's Books | Home",
header_text = "Welcome to Burt's Books!",
books = ['细说php','python','PHP','小时代']

将会通过参数传送到这里来
tornado的模板里可以使用python的代码,加上{% %}当使用if for while等要使用{% end %}结尾
代码中{% module Book(book) %} 将会调用入口服务文件中的定义和'Book'所对应的模块
ui_modules={'Hello':HelloModule,'Book':BookModule} 也就是BookModule,查看上面的BookModule定义


class BookModule(tornado.web.UIModule):
 def render(self,bookname):
   doubanapi = r'https://api.douban.com/v2/book/'
   searchapi = r'https://api.douban.com/v2/book/search?q='
   searchurl = searchapi+bookname
   searchresult = urllib2.urlopen(searchurl).read()
   bookid = json.loads(searchresult)['books'][0]['id']
   bookurl = doubanapi+bookid
   injson = urllib2.urlopen(bookurl).read()
   bookinfo = json.loads(injson)
   return self.render_string('modules/book.html',book = bookinfo)

BookModule 继承自tornado.web.UIModule,UI模块的使用是最后render_string()方法来把一个对象渲染到一个模板中去,我这里简单 的使用了豆瓣的图书api,先通过search来查询一下包含关键词的图书信息,返回第一条图书的id,再使用book api来查询该图书的具体信息,将这个具体图书的信息render到对应的模板
在templates 目录下创建modules目录,再下创建一个book.html,这里是具体的book要显示的内容框架


<div class="book">
 <h3 class="book_title">{{ book["title"] }}</h3>
 <a href="{{book['alt']}}" target="_blank"><p>点击查看详情</p></a>
 {% if book["subtitle"] != "" %}
   <h4 class="book_subtitle">{{ book["subtitle"] }}</h4>
 {% end %}
 <img src="{{ book["images"]["large"] }}" class="book_image"/>
 <div class="book_details">
   <div class="book_date_released">Released: {{ book["pubdate"]}}</div>    
   <h5>Description:</h5>
   <div class="book_body">{% raw book["summary"] %}</div>
 </div>
</div>

最后的文件目录结构应该是这样的

├── blockmain.py└── templates  ├── index.html  ├── main.html  └── modules    └── book.html

程序的执行是这样的:
先通过路径‘/'来使用MainHandler类访问index.html---->index.html继承自 main.html---->index.html中的{% module Book(book) %}反过来查找blockmain.py中的Book对应的ui_modules---->ui_modules中将查询得到的book对象内容渲 染到modules下的book.html中,这样就把完整的内容呈现出来了,没有做前端…… 通过python blockmain.py启动服务,通过http://localhost:8000 来访问得到如下的网页

使用Python的Tornado框架实现一个Web端图书展示页面

标签:Python,Tornado
0
投稿

猜你喜欢

  • 教你轻松掌握MaxDB和MySQL之间的协同性

    2009-02-23 17:28:00
  • python对象及面向对象技术详解

    2023-05-14 00:04:16
  • Python timer定时器两种常用方法解析

    2023-07-21 19:20:56
  • Python基于正则表达式实现文件内容替换的方法

    2023-08-23 00:14:09
  • python中使用zip函数出现<zip object at 0x02A9E418>错误的原因

    2021-02-24 02:37:14
  • Python基于requests实现模拟上传文件

    2023-09-30 01:42:05
  • php的优点总结 php有哪些优点

    2023-11-14 16:03:25
  • LotusPhp笔记之:基于ObjectUtil组件的使用分析

    2023-11-19 09:18:32
  • Python 3.x基础实战检查磁盘可用空间

    2021-05-11 09:21:25
  • ASP不允许同一个用户同时登陆两次

    2008-06-03 13:45:00
  • python如何爬取个性签名

    2021-03-29 03:34:04
  • Python根据字典的值查询出对应的键的方法

    2022-04-07 04:01:49
  • 原创一个AJAX类

    2008-07-24 13:29:00
  • MySQL与PHP的基础与应用专题之数据查询

    2023-11-10 10:09:55
  • PHP的PDO连接讲解

    2023-06-12 20:40:33
  • CodeIgniter分页类pagination使用方法示例

    2023-11-24 10:33:05
  • 浅谈python条件表达式:多项分支,双向分支

    2022-10-08 00:41:42
  • 函数式编程让JS更优美

    2008-06-10 12:40:00
  • python使用pandas读xlsx文件的实现

    2021-01-21 05:00:10
  • 判断 iframe 是否加载完成的完美方法

    2009-09-24 13:35:00
  • asp之家 网络编程 m.aspxhome.com