Flask依赖两个外部库:
- Jinja2模板引擎
- Werkzeng WSGI工具集。
使用pip安装flask的时候,这两个库会自动安装上。
pip install Flask
Jinja2
先简单的介绍下Jinja2:
Jinja2是一个设计灵活、快速和安全的python模板库。
- 使用pip安装jinja2(使用pip安装flask时会自动安装上。)
和安装flask一样
pip install Jinja2
- 基本API使用
最基本的方式是通过Template创建一个模板并渲染它。如果模板加载的来源不是从字符串而是从文件系统或其他数据来源时,不推荐这种方法。
from jinja2 import Template
template=Template('Hello {{ name }}!')
template.render(name='jinglepp')
通过创建一个Template实例得到一个新的模板对象,它提供了一个名为render()的方法,该方法调用使用dict或关键字参数展开模板。传递给模板的dict或关键字参数被叫做模板的context.
jinja2内部使用unicode.
可以在python模块的首行或第二行设置python编码
# -- coding: utf-8 --
- 基础
Jinja2使用一个名为Environment的中心对象。这个类的实例用于存储配置、全局对象,并用于从文件系统或其它位置加载模板。
即使你是通过字符串使用Template类的构造器创建的模板,environment对象也会自动被创建,尽管是共享的一个。
大多数应用会在程序初始化时创建一个Environment对象并使用它加载模板。在一些情况下,如果要使用不同的配置,使用多个environment对象是有用的。
在应用中使用Jinja2加载模板最简单的方式如下:
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
这将会以默认值创建一个模板环境和一个在当前应用python包中的templates文件夹中寻找模板的加载器。多个加载器是可用的,如果有需要从数据库或其他资源加载模板,可以自己写一个。
你只需要调用get_template()方法从这个环境中加载模板并返回已加载的Template:
template=env.get_template('mytemplate.html')
使用一些变量渲染模板只需要调用render():
print(template.render(the='variables',go='here')
使用模板加载器而不是向Template或Environment.from_string()传递字符串有很多好处,而且也使得模板继承成为可能。
Werkzeug
Werkzeug是Python的WSGI规范的实用函数库。使用广泛,基于BSD协议.
- 安装Werkzenug(使用pip安装flask时会自动安装上。)
pip install Werkzeug
你可以使用 pip 来安装依赖库:
pip install Jinja2 redis
直接写WSGI程序有点啰嗦,我应该很少情况下会用到这么底层的代码。
直接上个官方教程里的例子吧,原来的例子是python2的,我用的是python3,就自己边敲边改下。
由于还需要安装redis,我也不会用到它,不想安装,没办法测试下面的代码通过不通过
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import redis
from urllib.parse import urlparse
from werkzeug.wrappers import Request, Response
from werkzeug.routing import Map, Rule
from werkzeug.exceptions import HTTPException, NotFound
from werkzeug.wsgi import SharedDataMiddleware
from werkzeug.utils import redirect
from jinja2 import Environment, FileSystemLoader
class Shortly():
def __init__(self, config):
self.redis = redis.Redis(config['redis_host'], config['redis_port'])
template_path = os.path.join(os.path.dirname(__file__), 'templates')
self.jinja_env = Environment(loader=FileSystemLoader(template_path), autoescape=True)
self.url_map = Map([
Rule('/', endpoint='new_url'),
Rule('/', endpoint='follow_short_link'),
Rule('/+', endpoint='short_link_details')
])
def render_template(self, template_name, **context):
t = self.jinja_env.get_template(template_name)
return Response(t.render(context), mimetype='text/html')
def dispatch_request(self, request):
# return Response('Hello World!')
adapter = self.url_map.bind_to_environ(request.environ)
try:
endpoint, values = adapter.match()
return getattr(self, 'on_' + endpoint)(request, **values)
except HTTPException as e:
return e
def wsgi_app(self, environ, start_response):
request = Request(environ)
response = self.dispatch_request(request)
return response(environ, start_response)
def __call__(self, environ, start_response):
return self.wsgi_app(environ, start_response)
# 视图
def on_new_url(self, request):
error = None
url = ''
if request.method == 'POST':
url = request.form['url']
if not is_valid_url(url):
error = "请输入一个有效的URL"
else:
short_id = self.insert_url(url)
return redirect('/%s+' % short_id)
return self.render_template('new_url.html', error=error, url=url)
def on_follow_short_link(self, request, short_id):
link_target = self.redis.get('url-target:' + short_id)
if link_target is None:
raise NotFound()
self.redis.incr('click-count:' + short_id)
return redirect(link_target)
def on_short_link_details(self, request, short_id):
link_target = self.redis.get('url-target:' + short_id)
if link_target is None:
raise NotFound()
click_count = int(self.redis.get('click-count:' + short_id) or 0)
return self.render_template('short_link_details.html',
link_target=link_target,
short_id=short_id,
click_count=click_count
)
def insert_url(self, url):
short_id = self.redis.get('reverse-url:' + url)
if short_id is not None:
return short_id
url_num = self.redis.incr('last-url-id')
short_id = base36_encode(url_num)
self.redis.set('url-target:' + short_id, url)
self.redis.set('reverse-url:' + url, short_id)
return short_id
def create_app(redis_host='localhost', redis_port=6379, with_static=True):
app = Shortly({
'redis_host': redis_host,
'redis_port': redis_port
})
if with_static:
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
'/static': os.path.join(os.path.dirname(__file__), 'static')
})
return app
def is_valid_url(url):
parts = urlparse(url)
return parts.scheme in ('http', 'https')
def base36_encode(number):
assert number >= 0, "需要大于0的整数"
if number == 0:
return '0'
base36 = []
while number != 0:
number, i = divmod(number, 36)
base36.append('0123456788abcdefghijklmnopqrstuvwxyz'[i])
return ''.join(reversed(base36))
if __name__ == '__main__':
from werkzeug.serving import run_simple
app = create_app()
run_simple('127.0.0.1', 5000, app, use_debugger=True, use_reloader=True)
这些基础应该在学Flask的时候应该够用了,不够的地方可以再去查文档。
- Jinja2文档
- Werkzeug文档