安装flask
pip3 install flask
短小精悍、可扩展强 的一个Web框架。
牛逼点:上下文管理机制
依赖wsgi:
werkzeug(相当于Django的wsgi):只要安装flask,就有werkzeug了。
底层实现一: from werkzeug.wrappers import Request, Response from werkzeug.serving import run_simple 请求进来--------------------- def run(environ,start_response): return [b"asdfasdf"] 返回 if __name__ == '__main__': 监听4000端口 run_simple('localhost', 4000, run) 底层实现二: from werkzeug.wrappers import Request, Response @Request.application def hello(request): response对象也可以 return Response('Hello World!') if __name__ == '__main__': from werkzeug.serving import run_simple run_simple('localhost', 4000, hello)
备注:
flask源码入口
Flask源码入口: from werkzeug.wrappers import Response from werkzeug.serving import run_simple class Flask(object): def __call__(self,environ, start_response): response = Response('hello') return response(environ, start_response) def run(self): run_simple('127.0.0.1', 8000, self) app = Flask() if __name__ == '__main__': app.run()
class Foo(object): def __init__(self): print('sdfsdf') def __call__(self, *args, **kwargs): print('call') 类+()执行__init__方法 obj = Foo() 类+()执行__call__方法 obj()
简单使用:
from flask import Flask 步骤1实例化flask--------------- app = Flask(__name__) 步骤2视图函数------------------ @app.route('/index') def index(): return "Hello World" 步骤3运行--------------------------- if __name__ == '__main__': app.run()
给你一个路径 ,获取类并获取其中的大写的静态字段
给你一个路径 “settings.Foo”,可以找到类并获取去其中的大写的静态字段。
settings.py文件 class Foo: DEBUG = True TEST = True xx.py 文件 import importlib path = "settings.Foo" p,c = path.rsplit('.',maxsplit=1) m = importlib.import_module(p) cls = getattr(m,c) # 如果找到这个类? for key in dir(cls): if key.isupper(): print(key,getattr(cls,key))
flask系统组件:
1. 配置文件
app.py: app.config.from_object("settings.DevelopmentConfig") settings.py: class Config(object): DEBUG = False TESTING = False DATABASE_URI = 'sqlite://:memory:' class ProductionConfig(Config): DATABASE_URI = 'mysql://user@localhost/foo' 开发环境 class DevelopmentConfig(Config): DEBUG = True 测试环境 class TestingConfig(Config): TESTING = True
2. 路由系统
自定义装饰器放下面
- @app.route('/user/<username>'):不加类型是字符串
- @app.route('/post/<int:post_id>')整型
- @app.route('/post/<float:post_id>')小数
- @app.route('/post/<path:path>')路径
- @app.route('/login', methods=['GET', 'POST'])方法
- 自定义正则
1:无参数的反向解析:--------------------------------------------
导入url_for,指定endpoint名字,
不指定:默认是函数名
重名:项目无法启动
from flask import Flask,url_for app=Flask(__name__) @app.route('/indexaaaaa',methods=['GET','POST'],endpoint='n1') def index(): print(url_for('n1')) return 'Index' if __name__ == '__main__': app.run()
2:有参数的反向解析:----------------------------------------------------
from flask import Flask,url_for
app=Flask(__name__)
@app.route('/index/<int:nid>',methods=['GET','POST'],endpoint='n1')
def index(nid):
print(url_for('n1',nid=666))反向解析有参解析
return 'Index'
if __name__ == '__main__':
app.run()
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
from werkzeug.routing import BaseConverter from flask import Flask,url_for app = Flask(__name__) class RegexConverter(BaseConverter): """ 自定义URL匹配正则表达式 """ def __init__(self, map, regex): super(RegexConverter, self).__init__(map) self.regex = regex def to_python(self, value): """ 路由匹配时,匹配成功后传递给视图函数中参数的值 :param value: :return: """ return int(value) def to_url(self, value): """ 使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数 :param value: :return: """ val = super(RegexConverter, self).to_url(value) return val # 步骤二:添加到转换器 app.url_map.converters['reg'] = RegexConverter """ 1. 用户发送请求 2. flask内部进行正则匹配 3. 调用to_python(正则匹配的结果)方法 4. to_python方法的返回值会交给视图函数的参数 """ # 步骤三:使用自定义正则 @app.route('/index/<reg("\d+"):nid>') def index(nid): print(nid, type(nid)) print(url_for('index', nid=987)) return "index" if __name__ == '__main__': app.run()
3. 视图
FBV(基于函数的)
CBV(基于类的)
第一步导入views
from flask import Flask,views
第六步添加配置信息(不写则没有注释文件) import functools app = Flask(__name__) def wrapper(func):
第七步应用配置信息类 @functools.wraps(func):切记加上,否则被装饰的函数都成inner了。 def inner(*args,**kwargs): return func(*args,**kwargs) return inner 第二步定制一个类,继承views.MethodView类 class UserView(views.MethodView): methods = ['GET'] # 给CBV加装饰器 decorators = [wrapper,] def get(self,*args,**kwargs): return 'GET' def post(self,*args,**kwargs): return 'POST'
第三步:给函数添加路由 app.add_url_rule('/user',None,UserView.as_view('uuu')) if __name__ == '__main__':
第四步执行函数 app.run()
4. 请求相关
from flask import Flask,render_template,request,redirect,url_forapp = Flask(__name__)
@app.route('/login',methods=['GET','POST']) def login(): # 请求相关信息
常用方法
# request.method # request.form
# request.cookies # request.headers
# request.args
# request.values
# request.path # request.full_path # request.script_root # request.url # request.base_url # request.url_root # request.host_url # request.host
上传文件
# request.files # obj = request.files['the_file_name']
保存路径
# obj.save('/var/www/uploads/' + secure_filename(f.filename))
5. 响应
from flask import Flask,jsonify
响应体:
return “asdf”
return jsonify({'k1':'v1'}):返回json数据
return render_template('xxx.html')
return redirect()
定制响应头:
obj = make_response("asdf")
obj.headers['xxxxxxx'] = '123'
obj.set_cookie('key', 'value')
return obj
6. 模板渲染
- 基本数据类型:
可以执行python语法,如:dict.get() list['xx'] - 传入函数 - django,自动执行 - flask,不自动执行
--------------------------------------------------------------------------- - 全局定义函数(自定义方法),定义之后模板可以直接进行渲染 py文件定义: @app.template_global() def sb(a1, a2): return a1 + a2
模板使用:{{sb(1,9)}}
------------------------------------------------------------------------------- @app.template_filter() def db(a1, a2, a3): # {{ 1|db(2,3) }} return a1 + a2 + a3
模板中使用:{{1|db(2,3)}}
备注:1第一个参数存入,2第二个参数传入,3第三个参数传入
--------------------------------------------------------------------------------- - 模板继承 layout.html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <h1>模板</h1> {% block content %}{% endblock %} </body> </html> tpl.html {% extends "layout.html"%} {% block content %} {{users.0}} {% endblock %}
------------------------------------------------------------------------------------------------- - include {% include "form.html" %} form.html <form> asdfasdf asdfasdf asdf asdf </form>
------------------------------------------------------------------------------------------------ - 宏 {% macro ccccc(name, type='text', value='') %} <h1>宏</h1> <input type="{{ type }}" name="{{ name }}" value="{{ value }}"> <input type="submit" value="提交"> {% endmacro %} {{ ccccc('n1') }} {{ ccccc('n2') }}
------------------------------------------------------------------------------------------------------------- - 安全 - 前端: {{u|safe}} - 前端: MarkUp("asdf")
![](https://i-blog.csdnimg.cn/blog_migrate/eb501f861d7f927749a258725670e74e.png)
7. session
加密后放置在用户浏览器的cookie中。
- 流程:
- 请求到来
- 视图函数
- 请求结束
当请求刚到来:flask读取cookie中session对应的值:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95,将该值解密并反序列化成字典,
放入内存以便视图函数使用。 视图函数: @app.route('/ses') def ses(): session['k1'] = 123 session['k2'] = 456 del session['k1'] return "Session" session['xxx'] = 123 session['xxx'] 当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户cookie中。
8. 闪现
在session中存储一个数据,读取时通过pop将数据移除。只能读取一次 from flask import Flask,flash,get_flashed_messages @app.route('/page1') def page1(): flash('临时数据存储','error') flash('sdfsdf234234','error') flash('adasdfasdf','info') return "Session" @app.route('/page2') def page2(): print(get_flashed_messages(category_filter=['error'])) return "Session"
9. 中间件
- call方法什么时候触发? - 用户发起请求时,才执行。 - 任务:在执行call方法之前,做一个操作,call方法执行之后做一个操作。 class Middleware(object): def __init__(self,old): self.old = old def __call__(self, *args, **kwargs): ret = self.old(*args, **kwargs) return ret if __name__ == '__main__': app.wsgi_app = Middleware(app.wsgi_app) app.run()
10. 特殊装饰器
1. before_request(请求之前执行) 2. after_request(请求之后执行) 示例: from flask import Flask app = Flask(__name__) @app.before_request def x1(): print('before:x1') return '滚' @app.before_request def xx1(): print('before:xx1') @app.after_request def x2(response): print('after:x2') return response @app.after_request def xx2(response): print('after:xx2') return response @app.route('/index') def index(): print('index') return "Index" @app.route('/order') def order(): print('order') return "order" if __name__ == '__main__': app.run() 3. before_first_request(第一次访问时执行,再次访问不执行) from flask import Flask app = Flask(__name__) @app.before_first_request def x1(): print('123123') @app.route('/index') def index(): print('index') return "Index" @app.route('/order') def order(): print('order') return "order" if __name__ == '__main__': app.run() 给模板用的(在py文件中自定义的方法): 4. template_global 5. template_filter 6. errorhandler(没找到网页时定制信息,如显示企业广告或失联儿童等) @app.errorhandler(404) def not_found(arg): print(arg) return "没找到"
11.蓝图(flask目录结构)