IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

bottle高级使用技巧

Vimer 2012-04-22 14:52:40 累计浏览 2,583 次
本机暂存

之前对bottle做过不少的介绍,也写过一些文章来说明bottle的缺点,最近发现其实之前有些地方说的不太公平,所以趁此机会也来更正一下。

  • bottle是支持类似flask url_for的语法的,具体使用方法在下文介绍
  • bottle的request.query之类的参数默认是str类型,也是有原因的,比如我在给google做代理的时候,编码就不一定是utf8的,如果强制转化utf8就会报错
  • 之前的bug也得到了修正,比如mount('/x',app)之后,/x/和/x都可以访问到

OK,现在正式进入主题,我们来介绍一些bottle的一些高级使用


一. 智能创建url

这部分在bottle的文档上是没有介绍的(其实bottle明明实现了很多贴心的功能,不知道为啥都不写在文档上)。
在Bottle类里,有一个成员函数:

1
2
3
4
5
def get_url(self, routename, **kargs):
    """ Return a string that matches a named route """
    scriptname = request.environ.get('SCRIPT_NAME', '').strip('/') + '/'
    location = self.router.build(routename, **kargs).lstrip('/')
    return urljoin(urljoin('/', scriptname), location)

那么这个routename是哪里来的呢?看 route 装饰器的参数:

1
2
def route(self, path=None, method='GET', callback=None, name=None,
          apply=None, skip=None, **config):

其中的name参数就是routename(这里不得不说一下,这种方式比flask要好些,要用才指定name,而不需要为了实现url_for,把整个框架都实现的很复杂)

所以看到这里大家也就明白了,bottle的url生成器是绑定在Bottle实例上的,所以跨实例访问默认是做不到的。
而可能由于bottle所推崇的micro化,所以其源码中特意对默认Bottle示例包装出了一个函数:

1
2
3
4
5
for name in '''route get post put delete error mount
               hook install uninstall'''.split():
    globals()[name] = make_default_app_wrapper(name)
url = make_default_app_wrapper('get_url')
del name

这样做的好处是,如果工程只用到默认的Bottle实例的话,在模板中就可以直接使用url,而不必再多传个Bottle实例进去。

但是难免的,有时候我们确实涉及到跨实例生成url的,有没有办法呢?当然是有的,比较简单的方法如下:

1
2
3
4
5
6
7
from bottle import default_app
 
import x
 
local.x_app = x.app
 
app.mount('/x', x.app)

这样在模板中就可以直接通过如下方式来访问:

1
{{ local.x_app.get_url('hello', name='ai', x=1) }}

但是怎么才能让模板能够访问到local变量呢?我们接下来介绍


二. 给模板指定默认的变量

因为笔者用的最多的是jinja2,所以模板相关的介绍都是以jinja2为例子.
由于bottle的很多实例都是使用的代理模式,如request,response,local,所以我们可以放心的将这些变量传入到模板默认变量里去。
代码也很简单:

1
2
3
4
5
6
7
from bottle import BaseTemplate
 
BaseTemplate.defaults.update(dict(
    request=request,
    local=local,
    )
)

有兴趣的话,大家也可以去直接看一下源码,很好懂


三. 给模板增加filters

还是以jinja2为例,直接给出代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from bottle import BaseTemplate
 
if 'filters' not in BaseTemplate.settings:
    BaseTemplate.settings['filters'] = {}
 
filters = BaseTemplate.settings['filters']
 
def urlencode_filter(params):
    '''
    urlencode
    '''
    from urllib import urlencode
 
    return urlencode(params)
 
filters.update(dict(
    urlencode=urlencode_filter,
    )
)

OK,一共就是这些,这里基于的bottle版本是 0.10.9,如果有不相符的地方,请查看bottle版本。

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 用Hyer来进行网站的抓取 (累计阅读 158,251)
  2. 配置Nginx+uwsgi更方便地部署python应用 (累计阅读 107,164)
  3. 程序员技术练级攻略 (累计阅读 35,471)
  4. python实现自动登录discuz论坛 (累计阅读 32,834)
  5. python编程细节──遍历dict的两种方法比较 (累计阅读 20,371)
  6. 每个程序员都应该学习使用Python或Ruby (累计阅读 17,918)
  7. Chrome和goagent的配置方法,你懂的 (累计阅读 16,843)
  8. 30分钟3300%性能提升――python+memcached网页优化小记 (累计阅读 13,742)
  9. 使用python爬虫抓站的一些技巧总结:进阶篇 (累计阅读 13,301)
  10. 我的PHP,Python和Ruby之路 (累计阅读 13,147)