flask 配置文件 路由 视图 模板 中间件
今日概要
- wsgi
- 创建flask对象
- 模板
- 静态文件
- 路由系统
- 路由的应用:装饰器(推荐)、方法
- 动态路由
- 视图
- FBV
- CBV
- 模板
- 继承
- include
- 自定义标签
- 特殊装饰器
- before_request充当中间件角色
wsgi 找源码的流程
不依赖与flask
from werkzeug.serving import run_simple
from werkzeug.wrappers import BaseResponse
def func(environ, start_response):
print('请求来了')
response = BaseResponse('你好')
return response(environ, start_response)
if __name__ == '__main__':
run_simple('127.0.0.1', 5000, func)
"""
1.程序启动,等待用户请求到来
app.run()
2.用户请求到来 app()
app.__call__
"""
from flask import Flask
app = Flask(__name__)
@app.route('/index')
def index():
return 'hello world'
if __name__ == '__main__':
app.run()
flask对象静态文件的处理
静态文件的处理。
view
from flask import Flask,render_template
app = Flask(__name__,template_folder='templates',static_folder='static',static_url_path='/xx')
@app.route('/index')
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run()
#static_folder参数代表静态文件夹名字
#static_folder参数 相当与别名 用这个别名就可以找到文件夹
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>首页</h1>
<!-- <img src="/xx/mm.jpg" />-->
<!-- 建议 -->
<img src="{{ url_for('static',filename='mm.jpg')}}" />
</body>
</html>
#static会自动帮你找 不管你是什么 xx还是什么
配置文件
创建一个config文件夹 里面有 配置文件全局setting.py与局部localsettings.py
配置文件
py文件导入
配置文件尽量大写
# app.py<br>from flask import Flask
app = Flask(__name__)
app.config.from_pyfile("settings.py") # 加载配置文件setting
print(app.config['XX'])#打印配置文件中的XX变量
@app.route("/")
def index():
return "hello"
if __name__ == '__main__':
app.run()
# settings.py
DEBUG = True
...
setting.py
#方便测试
try:
from .localsettings import *
except ImportError:
pass
localsettings.py
用于自己测试
XX=11
基于类的方式 路径方式导入
app.py
from flask import Flask
app = Flask(__name__)
app.config.from_object("test.settings.TestingConfig") # 系统环境需能找到的模块路径,默认在app同级目录下
app.config.from_object("test.settings.Config") #加载
@app.route("/")
def index():
return "hello"
if __name__ == '__main__':
app.run()
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
路由系统
-
路由的两种写法
def index(): return render_template('index.html') app.add_url_rule('/index', 'index', index) # 公司里一般用这种方式 @app.route('/login') def login(): return render_template('login.html')
-
路由加载的源码流程
- 将url和函数打包成为 rule 对象 - 将rule对象添加到map对象中。 - app.url_map = map对象
-
动态路由
@app.route('/login') def login(): return render_template('login.html') @app.route('/login/<name>') def login(name): print(type(name)) return render_template('login.html') @app.route('/login/<int:name>') def login(name): print(type(name))#int类型 return render_template('login.html')
-
支持正则表达式的路由
from flask import Flask,render_template app = Flask(__name__) #----------------- 固定写法 from werkzeug.routing import BaseConverter class RegConverter(BaseConverter): def __init__(self, map, regex): super().__init__(map) self.regex = regex app.url_map.converters['regex'] = RegConverter #-------------------- @app.route('/index/<regex("\d+"):x1>') def index(x1): return render_template('index.html') if __name__ == '__main__': app.run()
视图
FBV
def index():
return render_template('index.html')
app.add_url_rule('/index', 'index', index)
# 公司里一般用这种方式
@app.route('/login')
def login():
return render_template('login.html')
CBV
from flask import Flask,render_template,views
app = Flask(__name__,)
def test1(func):
def inner(*args,**kwargs):
print('before1')
result = func(*args,**kwargs)
print('after1')
return result
return inner
def test2(func):
def inner(*args,**kwargs):
print('before2')
result = func(*args,**kwargs)
print('after2')
return result
return inner
class UserView(views.MethodView):
methods = ['GET',"POST"]#设置可以通过的请求
decorators = [test1,test2]#设置可以通过的方法
def get(self):
print('get')
return 'get'
def post(self):
print('post')
return 'post'
app.add_url_rule('/user',view_func=UserView.as_view('user')) # endpoint
if __name__ == '__main__':
app.run()
模板
基本用法
flask比django更加接近Python。
from flask import Flask,render_template
app = Flask(__name__,)
def func(arg):
return '你好' + arg
@app.route('/md')
def index():
nums = [11,222,33]
return render_template('md.html',nums=nums,f=func)
if __name__ == '__main__':
app.run()
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>头</h1>
{% block content %} {% endblock %}
<h1>底</h1>
</body>
</html>
组件
<form action="">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
</form>
继承模板 使用组件 使用函数
{% extends 'layout.html' %}
{% block content %}
<h1>MD</h1>
{% include 'form.html' %}
{{ f("汪洋") }}
{% endblock %}
定义全局模板方法
from flask import Flask,render_template
app = Flask(__name__,)
#在哪个模板都可以用
@app.template_global() # 使用方法1 {{ func("赵海宇") }}
def func(arg):
return '海狗子' + arg
@app.template_filter() #使用方法2 {{ "赵海宇"|x1("孙宇") }}
def x1(arg,name):
return '海狗子' + arg + name
@app.route('/md/hg')
def index():
return render_template('md_hg.html')
if __name__ == '__main__':
app.run()
注意:在蓝图中注册时候,应范围只有本蓝图。
特殊装饰器 类似中间件
类似中间件
from flask import Flask,render_template,request
app = Flask(__name__)
@app.before_request#视图函数前执行
def f1():
if request.path == '/login':
return
print('f1')
# return '123'#有返回值就不会往下执行了
@app.after_request#视图函数后执行
def f10(response):
print('f10')
return response
@app.route('/index')
def index():
print('index')
return render_template('index.html')
if __name__ == '__main__':
app.run()
多个装饰器
from flask import Flask,render_template,request
app = Flask(__name__)
@app.before_request
def f1():
print('f1')
@app.before_request
def f2():
print('f2')
@app.after_request
def f10(response):
print('f10')
return response
@app.after_request
def f20(response):
print('f20')
return response
@app.route('/index')
def index():
print('index')
return render_template('index.html')
if __name__ == '__main__':
app.run()
app.__call__
注意:before_after request可以在蓝图中定义,在蓝图中定义的话,作用域只在本蓝图。
小细节
from flask import Flask,render_template
app = Flask(__name__,)
@app.route('/index')
def index():
return render_template('index.html')
@app.before_request
def func():
print('xxx')
#另一种写法
def x1():
print('xxx')
app.before_request(x1)
if __name__ == '__main__':
app.run()
赠送:threading.local
https://www.cnblogs.com/aaronthon/p/9457330.html
假如,开了十个线程并且做同样的一件事,他们需要带着自己的数据进来,完成事情后带着自己的数据出去。如果是并发,同时进来,他们的数据就会混乱。
一般情况,我们加锁就可以了,一个人先进来,先加锁,另一个人过来看到加锁了,就在外面等,等里面的人出来,自己进去加锁,这样就不会出现数据混乱的问题。
另一种解决方法就是threading.local()来解决问题。
import time
import threading
# 当每个线程在执行 val1.xx=1 ,在内部会为此线程开辟一个空间,来存储 xx=1
# val1.xx,找到此线程自己的内存地址去取自己存储 xx
val1 = threading.local()
def task(i):
val1.num = i
time.sleep(1)
print(val1.num)
for i in range(4):
t = threading.Thread(target=task,args=(i,))
t.start()
非学,无以致疑;非问,无以广识