Flask框架知识系列之一

1,Flask框架的诞生:

Flask诞生于2010年,是Armin ronacher(人名)用Python语言基于Werkzeug工具箱编写的轻量级Web开发框架。它主要面向需求简单的小应用。

Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login),都需要用第三方的扩展来实现。比如可以用Flask-extension加入ORM、窗体验证工具,文件上传、身份验证等。Flask没有默认使用的数据库,你可以选择MySQL,也可以用NoSQL。其 WSGI 工具箱采用 Werkzeug(路由模块) ,模板引擎则使用 Jinja2 。

可以说Flask框架的核心就是Werkzeug和Jinja2。

Python最出名的框架要数Django,此外还有Flask、Tornado等框架。
虽然Flask不是最出名的框架,但是Flask应该算是最灵活的框架之一,这也是Flask受到广大开发者喜爱的原因。

2,Flask部分扩展包:

Flask-SQLalchemy:操作数据库;
Flask-migrate:管理迁移数据库;
Flask-Mail:邮件;
Flask-WTF:表单;
Flask-Bable:提供国际化和本地化支持,翻译;
Flask-script:插入脚本;
Flask-Login:认证用户状态;
Flask-OpenID:认证;
Flask-RESTful:开发REST API的工具;
Flask-Bootstrap:集成前端Twitter Bootstrap框架;
Flask-Moment:本地化日期和时间;

3,Flask参考网站

中文文档(http://docs.jinkan.org/docs/flask/

英文文档(http://flask.pocoo.org/docs/0.11/

4,第一个Hello Flask程序

Flask程序运行过程:

所有Flask程序必须有一个程序实例。

Flask调用视图函数后,会将视图函数的返回值作为响应的内容,返回给客户端。
一般情况下,响应内容主要是字符串和状态码。

当客户端想要获取资源时,一般会通过浏览器发起HTTP请求。
此时,Web服务器使用WSGI(Web Server Gateway Interface)协议,把来自客户端的所有请求都交给Flask程序实例,程序实例使用Werkzeug来做路由分发(URL请求和视图函数之间的对应关系)。
根据每个URL请求,找到具体的视图函数。
在Flask程序中,路由的实现一般是通过程序实例的装饰器实现。
通过调用视图函数,获取到数据后,把数据传入HTML模板文件中,模板引擎负责渲染HTTP响应数据,然后由Flask返回响应数据给浏览器,最后浏览器处理返回的结果显示给客户端。

示例:


#导入Flask类
from flask import Flask

#Flask函数接收一个参数name,它会指向程序所在的模块
'''
注意:name可以传入的参数:
1,字符串:‘hello’,但是‘abc’,不行,因为abc是python内置的模块
2,__name__

不可以插入的参数
1,python内置的模块,re,urllib,abc等
2,数字
'''

app = Flask(__name__)

#装饰器的作用是将路由映射到视图函数index
@app.route('/')
def index():
    return 'Hello Flask'
    
#Flask应用程序实例的run方法启动WEB服务器
if __name__ == '__main__':
    app.run()

5,默认的URL和正则URL

@app.route('<URL>')中URL显式支持string、int、float、path 4种类型,隐式支持正则

5.1默认的url

分析源码(在routing.py文件中,大概1092行中)发现url支持以下几种类型

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

5.2正则URL的实现

第一步,写正则类,继承BaseConverter,将匹配到的值设置为regex的值就可以了

class RegexUrl(BaseConverter):
    def __init__(self, url_map, *args):
        super(RegexUrl, self).__init__(url_map)
        self.regex = args[0]

第二步,把正则类赋值给我们定义的正则规则

app.url_map.converters['re'] = RegexUrl

第三步,在URL中使用正则

@app.route('/regex/<re("[a-z]{3}"):id>')
def regex(id):
    return 'id:%s'%id

6,Flask中钩子的理解和应用

钩子是通过装饰器的形式实现的,支持以下四种

  1. before_first_request:在处理第一个请求前运行
  2. before_request:在每次请求前运行
  3. after_request:如果没有未处理的异常抛出,在每次请求后运行
  4. teardown_request:即使有未处理的异常抛出,在每次请求后运行

应用:

@api.after_request
def after_request(response):
    """设置默认的响应报文格式为application/json"""
    # 如果响应报文response的Content-Type是以text开头,则将其改为默认的json类型
    if response.headers.get("Content-Type").startswith("text"):
        response.headers["Content-Type"] = "application/json"
return response

7,自定义过滤器的步骤如下:

第一步:先定义自定义过滤器函数

def count_substring(string, substring):
    return string.count(substring)

第二步:注册自己定义的过滤器

app.jinja_env.filters['count_substring'] = count_substring

第三步:最后在模板文件html中直接使用注册时的键名

{#前面的作为原字符串string,传入的作为子字符串substring#}
{{ 'A long long long long long  long longabc string ' | count_substring('long') }}<br/>

8,什么是Werkzeug?

Werkzeug是WSGI协议层工具集。
WSGI本身是一个用来确保你的web应用能够与webserver进行对话,
更重要的是,确保web应用之间能够一起配合工作的协议或约定。

在没有Werkzeug帮助下,用WSGI实现的一个基本“Hello World”应用看起来是这样的:

def application(environ, start_response):  
    start_response(‘200 OK’, [(‘Content-Type’, ‘text/plain’)])  
    return [‘Hello World!’]  

WSGI应用是你可以调用、传递一个environ字典和一个start_response函数的东西。
environ包含所有的传入信息,start_response函数可以用来指示response的开始。

使用Werkzeug之后,你将不再需要直接处理被提交上来的请求(request)和应答(response)对象。
请求数据获取environ对象,并允许你以一种良好的方式访问environ中的数据。
response对象本身也是一个WSGI应用,提供了很多友好的创建response的方法。
下面的代码演示了如何编写带有response对象的应用:

from werkzeug.wrappers import Response  
def application(environ, start_response):  
    response = Response(‘Hello World!’, mimetype=‘text/plain’)  
    return response(environ, start_response)  

9,flask-script指令第三方扩展

第一种——创建Command子类

Command子类必须定义一个run方法;
举例:创建Hello命令,并将Hello命令加入Manager实例


from flask_script import Manager  
from flask_script import Command  
from debug import app  
  
manager = Manager(app)  
  
class Hello(Command):  
    'hello world'  
    def run(self):  
        print 'hello world'  
  
manager.add_command('hello', Hello())  

def make_shell_context():
    return dict(app = app, db=db)

manager.add_command("shell",Shell(make_context=make_shell_context))
  
if __name__ == '__main__':  
    manager.run()

第二种——使用Command实例的@command修饰符

from flask_script import Manager  
from debug import app  
  
manager = Manager(app)  
 
@manager.command  
def hello():  
    'hello world'  
    print 'hello world'  
  
if __name__ == '__main__':  
    manager.run()

第三种——使用Command实例的@option修饰符

复杂情况下,建议使用@option;
可以有多个@option选项参数

10,请求上下文和应用上下文的区别

current_app、g就是应用上下文
requests、session就是请求上下文

手动创建上下文的两种方法:
with app.app_context()
app = current_app._get_current_object()

11,Flask特有的变量和函数

config

你可以从模板中直接访问Flask当前的config对象:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:xiaoke@127.0.0.1:3306/test'

request:

就是flask中代表当前请求的request对象:
http://127.0.0.1

session

为Flask的session对象

注意:

flask中有三个session:
第一个:数据库中的session,例如:db.session.add()
第二个:在flask_session扩展中的session,使用:from flask_session import Session,使用第三方扩展的session可以把信息存储在服务器中,客户端浏览器中只存储sessionid
第三个:flask自带的session,是一个请求上下文, 使用:from flask import session。自带的session把信息加密后都存储在客户端的浏览器cookie中

url_for()

url_for会根据传入的路由器函数名,返回该路由对应的URL,在模板中始终使用url_for()就可以安全的修改路由绑定的URL,则不比担心模板中渲染出错的链接:

{ {url_for('home')} }

如果我们定义的路由URL是带有参数的,则可以把它们作为关键字参数传入url_for(),Flask 会把他们填充进最终生成的URL中:

{ { url_for('post', post_id=1)} }
/post/1

get_flashed_messages()

这个函数会返回之前在flask中通过flash()传入的消息的列表,
flash函数的作用很简单,可以把由Python字符串表示的消息加入一个消息队列中,再使用get_flashed_messages()函数取出它们并消费掉:

{ %for message in get_flashed_messages()% }
    message
{ %endfor% }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容