在正式开始Web开发前,我们需要编写一个Web框架。

为什么不选择一个现成的Web框架而是自己从头开发呢?我们来考察一下现有的流行的Web框架:

Django:一站式开发框架,但不利于定制化;

web.py:使用类而不是更简单的函数来处理URL,并且URL映射是单独配置的;

Flask:使用@decorator的URL路由不错,但框架对应用程序的代码入侵太强;

bottle:缺少根据URL模式进行拦截的功能,不利于做权限检查。

所以,我们综合几种框架的优点,设计一个简单、灵活、入侵性极小的Web框架。

设计Web框架

一个简单的URL框架应该允许以@decorator方式直接把URL映射到函数上:

# 首页:

@get('/')

def index():

return '

Index page

'

# 带参数的URL:

@get('/user/:id')

def show_user(id):

user = User.get(id)

return 'hello, %s' % user.name

有没有@decorator不改变函数行为,也就是说,Web框架的API入侵性很小,你可以直接测试函数show_user(id)而不需要启动Web服务器。

函数可以返回str、unicode以及iterator,这些数据可以直接作为字符串返回给浏览器。

其次,Web框架要支持URL拦截器,这样,我们就可以根据URL做权限检查:

@interceptor('/manage/')

def check_manage_url(next):

if current_user.isAdmin():

return next()

else:

raise seeother('/signin')

拦截器接受一个next函数,这样,一个拦截器可以决定调用next()继续处理请求还是直接返回。

为了支持MVC,Web框架需要支持模板,但是我们不限定使用哪一种模板,可以选择jinja2,也可以选择mako、Cheetah等等。

要统一模板的接口,函数可以返回dict并配合@view来渲染模板:

@view('index.html')

@get('/')

def index():

return dict(blogs=get_recent_blogs(), user=get_current_user())

如果需要从form表单或者URL的querystring获取用户输入的数据,就需要访问request对象,如果要设置特定的Content-Type、设置Cookie等,就需要访问response对象。request和response对象应该从一个唯一的ThreadLocal中获取:

@get('/test')

def test():

input_data = ctx.request.input()

ctx.response.content_type = 'text/plain'

ctx.response.set_cookie('name', 'value', expires=3600)

return 'result'

最后,如果需要重定向、或者返回一个HTTP错误码,最好的方法是直接抛出异常,例如,重定向到登陆页:

raise seeother('/signin')

返回404错误:

raise notfound()

基于以上接口,我们就可以实现Web框架了。

实现Web框架

最基本的几个对象如下:

# transwarp/web.py

# 全局ThreadLocal对象:

ctx = threading.local()

# HTTP错误类:

class HttpError(Exception):

pass

# request对象:

class Request(object):

# 根据key返回value:

def get(self, key, default=None):

pass

# 返回key-value的dict:

def input(self):

pass

# 返回URL的path:

@property

def path_info(self):

pass

# 返回HTTP Headers:

@property

def headers(self):

pass

# 根据key返回Cookie value:

def cookie(self, name, default=None):

pass

# response对象:

class Response(object):

# 设置header:

def set_header(self, key, value):

pass

# 设置Cookie:

def set_cookie(self, name, value, max_age=None, expires=None, path='/'):

pass

# 设置status:

@property

def status(self):

pass

@status.setter

def status(self, value):

pass

# 定义GET:

def get(path):

pass

# 定义POST:

def post(path):

pass

# 定义模板:

def view(path):

pass

# 定义拦截器:

def interceptor(pattern):

pass

# 定义模板引擎:

class TemplateEngine(object):

def __call__(self, path, model):

pass

# 缺省使用jinja2:

class Jinja2TemplateEngine(TemplateEngine):

def __init__(self, templ_dir, **kw):

from jinja2 import Environment, FileSystemLoader

self._env = Environment(loader=FileSystemLoader(templ_dir), **kw)

def __call__(self, path, model):

return self._env.get_template(path).render(**model).encode('utf-8')

把上面的定义填充完毕,我们就只剩下一件事情:定义全局WSGIApplication的类,实现WSGI接口,然后,通过配置启动,就完成了整个Web框架的工作。

设计WSGIApplication要充分考虑开发模式(Development Mode)和产品模式(Production Mode)的区分。在产品模式下,WSGIApplication需要直接提供WSGI接口给服务器,让服务器调用该接口,而在开发模式下,我们更希望能通过app.run()直接启动服务器进行开发调试:

wsgi = WSGIApplication()

if __name__ == '__main__':

wsgi.run()

else:

application = wsgi.get_wsgi_application()

因此,WSGIApplication定义如下:

class WSGIApplication(object):

def __init__(self, document_root=None, **kw):

pass

# 添加一个URL定义:

def add_url(self, func):

pass

# 添加一个Interceptor定义:

def add_interceptor(self, func):

pass

# 设置TemplateEngine:

@property

def template_engine(self):

pass

@template_engine.setter

def template_engine(self, engine):

pass

# 返回WSGI处理函数:

def get_wsgi_application(self):

def wsgi(env, start_response):

pass

return wsgi

# 开发模式下直接启动服务器:

def run(self, port=9000, host='127.0.0.1'):

from wsgiref.simple_server import make_server

server = make_server(host, port, self.get_wsgi_application())

server.serve_forever()

Try

把WSGIApplication类填充完毕,我们就得到了一个完整的Web框架。

python程序框架的描述_简单介绍Python下自己编写web框架的一些要点相关推荐

  1. python协程异步原理_简单介绍Python的Tornado框架中的协程异步实现原理

    Tornado 4.0 已经发布了很长一段时间了, 新版本广泛的应用了协程(Future)特性. 我们目前已经将 Tornado 升级到最新版本, 而且也大量的使用协程特性. 很长时间没有更新博客, ...

  2. python内存的回收机制_简单介绍python的垃圾回收机制

    这篇文章主要介绍了python垃圾回收机制的相关资料,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下 什么是垃圾回收机制? 首先,咱先来解释名词,垃圾回收是不是就是将没用的,废弃的东西回 ...

  3. python队列来做什么_简单介绍python的双向队列

    介绍 大家都知道利用 .append 和 .pop 方法,我们可以把列表当作栈或者队列来用(比如,把 append 和 pop(0) 合起来用,就能模拟栈的"先进先出"的特点).但 ...

  4. python floor是什么意思_简单介绍Python中的floor()方法

    floor()方法返回不大于x的最大整数(向下取整). 语法 以下是floor()方法的语法: import math math.floor( x ) 注意:此函数是无法直接访问的,所以我们需要导入m ...

  5. python中len用法_简单介绍Python中的len()函数的使用

    简单介绍Python中的len()函数的使用 函数:len() 1:作用:返回字符串.列表.字典.元组等长度 2:语法:len(str) 3:参数:str:要计算的字符串.列表.字典.元组等 4:返回 ...

  6. 简述python中的几种数据类型,简单介绍Python中的几种数据类型

    简单介绍Python中的几种数据类型 python 里面分为 基本数据类型 和 复合数据类型 基本数据类型包括:数值 字符串 布尔 和 none 复合数据类型包括:列表 元组 字典 和集合怎么算是深情 ...

  7. python协同过滤调用包_简单的python协同过滤程序实例代码

    本文研究的主要是python协同过滤程序的相关内容,具体介绍如下. 关于协同过滤的一个最经典的例子就是看电影,有时候不知道哪一部电影是我们喜欢的或者评分比较高的,那么通常的做法就是问问周围的朋友,看看 ...

  8. python打开excel窗口_简单介绍python在CMD界面读取excel所有数据

    这篇文章主要介绍了python在CMD界面读取excel所有数据,帮助大家更好的利用python办公,感兴趣的朋友可以了解下 代码 import xlrd import os from prettyt ...

  9. python语言中运算符号_详细介绍Python语言中的按位运算符

    <从问题到程序:用Python学编程和计算>--2.11 补充材料 本节书摘来自华章计算机<从问题到程序:用Python学编程和计算>一书中的第2章,第2.11节,作者:裘宗燕 ...

最新文章

  1. Java黑皮书课后题第1章:1.12(以千米计的平均速度)假设一个跑步者1小时40分35秒跑了24英里。编写一个程序显示以每小时为多少千米为单位的平均速度值(1英里等于1.6千米)
  2. mysql数据库局限性_Mysql分区表局限性总结
  3. 《下辈子还教书》经典语录(1)
  4. 区块链究竟是什么?看完这篇秒懂!
  5. 【NOIP2015】【Luogu2678】跳石头
  6. fstatfs/statfs详解
  7. 澳洲大学计算机本科课程,澳洲留学 澳洲大学的本科课程分为6大类
  8. PRAM模型与Amdahl定律
  9. 保利威视视频云平台 新版本(Version 1.1.0) 上线通知
  10. ubuntu 浏览器flash插件安装
  11. 网络直播课程:神马是敏捷?(直播时间:2014-7-14 20:00-21:00)
  12. vue 动态渲染图片 不出来
  13. NAACL 2022事件相关(事件抽取、事件关系抽取、事件预测等)论文汇总
  14. bat文件调用CMD命令快速显示ip
  15. 面试集锦之计算机操作系统
  16. Linux 入门——基础使用及常见命令
  17. Outlook 2010不能打开邮件中IE地址链接解决办法
  18. 局域网共享工具_局域网共享精灵,一款助力于局域网环境下文件共享和打印机共享的系统工具软件...
  19. 计算机科学与技术到底是什么?
  20. 51单片机c语言定义寄存器r,c51特殊功能寄存器定义及作用

热门文章

  1. Laravel框架一:原理机制篇
  2. gulp入坑系列(1)——安装gulp
  3. jQuery 事件 - bind() 方法
  4. eclipse快捷键Alt + /
  5. 双向(端)链表、栈、队列
  6. 【数据结构与算法】复杂度分析
  7. boa服务器实现温湿度显示,SMT车间温湿度分布式远程监控系统的设计
  8. templatefield 动态_GridView动态创建templateField | 学步园
  9. LinuX 硬盘分区细节详谈 【 整理至 LinuxSir BY FreeXploiT 】
  10. linux 内核3.8,[Beaglebone] BBB迁移到linux 3.8实时内核