flask基础(1)
# 链接资料
老男孩:<https://www.cnblogs.com/wupeiqi/articles/7552008.html>
flask官网插件:<https://flask.palletsprojects.com/en/2.1.x/extensions/>
flask中文官网:<https://flask.net.cn/>
flask w3cschool:<https://www.w3cschool.cn/flask/flask_message_flashing.html>
<http://www.coolpython.net/flask_tutorial/deep-learn/what-is-wsgi.html>
2
3
4
5
# day01
谈谈对pythonWeb框架:
- django:大而全,内部提供,ORM、Admin、中间件、From、ModelForm、Session、缓存、信号、CSR等
- flask:短小精悍,可扩展强,第三方组件丰富。
- tornado:短小精悍+异步非阻塞
- 其他:
wsgi通信
django,wsgiref
flask,werkzurg
from werkzeug.wrappers import Request, Response from werkzeug.serving import run_simple @Request.application def hello(request): return Response('Hello World!') if __name__ == '__main__': run_simple('localhost', 4000, hello)
1
2
3
4
5
6
7
8
9
10
# 作业:
作业:
1. 路飞
2. Flask
- 装饰器实现
- 位置
- url起别名(不能重复)
- 类似django中间件的东西:before_request装饰器
3. 上下文预习:
a. threading.local
b.
functools.wraps
functools.partial
c. 面向对象封装
d. 面向对象中:
__setattr__
__getattr__
__delattr__
4. 预习:
<http://www.cnblogs.com/wupeiqi/articles/7552008.html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# day02
# 内容回顾
# 1. 装饰器
问题:什么是装饰器?
问题:手写装饰器
问题:装饰器都在哪里用过?
import functools
def wapper(func):
@functools.wraps(func) # 使用__name__可以返回原函数名,不使用的话没有
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
"""
1. 执行wapper函数,并将被装饰的函数当做参数。 wapper(index)
2. 将第一步的返回值,重新赋值给 新index = wapper(老index)
"""
@wapper
def index(a1):
return a1 + 1000
@wapper
def order(a1):
return a1 + 1000
print(index.__name__)
print(order.__name__)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 2. 谈谈你对面向对象的认识?
- 封装:
- 将同一类方法分为一类:方法封装到类中
- 将方法中共同的参数封装到对象中:把共用值封装到对象中。
情况:
a. BaseReponse
def index(a1,a2,a3,a4,a5,a6,a7):
pass
# 用户类实现
class Foo(object):
def __init__(self,a1,a2,a3,a4,a5,a6,a7):
self.a1 = a1
self.a2 = a2
self.a3 = a3
self.a4 = a4
self.a5 = a5
self.a6 = a6
self.a7 = a7
def index(obj):
pass
b. 给了一些值,将数据加工: django 自定义分页
class Foo(object):
def __init__(self,a1,a2,a3,a4,a5,a6,a7):
self.a1 = a1
self.a2 = a2
self.a3 = a3
self.a4 = a4
self.a5 = a5
self.a6 = a6
self.a7 = a7
def 金条(self):
return self.a1 + self.a2
def 手表(self):
return self.a1 + self.a7
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 今日内容
# 1、配置文件
# a.创建一个配置文件settings.py (opens new window)
class BaseConfig(object):
DEBUG = True # 公共配置
SECRET_KEY = "asudflkjdfadjfakdf"
class ProductionConfig(BaseConfig):
"""生产环境"""
DEBUG = False
class DevelopmentConfig(BaseConfig):
"""开发配置"""
pass
class TestingConfig(BaseConfig):
"""测试环境"""
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# b. 在flask中使用配置
from flask import Flask, render_template, redirect
app = Flask(__name__)
# 配置文件
app.config.from_object("settings.DevelopmentConfig") # 引入
@app.route('/index', methods=['GET', 'POST'])
def index():
return "f
if __name__ == '__main__':
app.run()
2
3
4
5
6
7
8
9
10
11
12
13
# 其他方式(更多配置)
# 更多配置:<https://www.cnblogs.com/wupeiqi/articles/7552008.html>
方式一:
app.config['DEBUG'] = True
PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)
方式二:
app.config.from_pyfile("python文件名称")
如:
settings.py
DEBUG = True
app.config.from_pyfile("settings.py")
app.config.from_envvar("环境变量名称")
环境变量的值为python文件名称名称,内部调用from_pyfile方法
app.config.from_json("json文件名称")
JSON文件名称,必须是json格式,因为内部会执行json.loads
app.config.from_mapping({'DEBUG':True})
字典格式
app.config.from_object("python类或类的路径")
app.config.from_object('pro_flask.settings.TestingConfig')
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
PS: 从sys.path中已经存在路径开始写
PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 2、路由
# 1. 添加路由的二种方式
多看源码
from flask import Flask, render_template, redirect
app = Flask(__name__)
"""
1. 执行decorator=app.route('/index',methods=['GET','POST'])
2. @decorator
- decorator(index)
# 内部执行的方法
def decorator(f: F) -> F:
endpoint = options.pop("endpoint", None)
self.add_url_rule(rule, endpoint, f, **options)
return f # 返回函数名
return decorator
"""
# 路由方式一(*):
@app.route('/index', methods=['GET', 'POST'])
def index():
return "Index"
# 路由方式二:
def order():
return 'Order'
app.add_url_rule('/order', view_func=order)
if __name__ == '__main__':
app.run()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 2.反向生成url(url_for)/设置路由的别名(endpoint)
通过添加endpoint('别名')参数设置别名,默认为函数名。
通过url_for('别名','参数')得到路由url
from flask import Flask, render_template, redirect, url_for
app = Flask(__name__)
"""
通过添加endpoint参数设置别名,默认为函数名,通过url_for('别名')得到路由url
"""
@app.route('/index1', methods=['GET', 'POST'], endpoint='n1') # <http://127.0.0.1:5000/index1>
def index():
v1 = url_for('n1')
v2 = url_for('n2') # 反向生成url
v3 = url_for('logout')
print(v1, v2, v3) # /index1 /login1 /logout1
return "Index"
@app.route('/login1', methods=['GET', 'POST'], endpoint='n2')
def login():
return "login"
@app.route('/logout1', methods=['GET', 'POST'])
def logout():
return "logout"
if __name__ == '__main__':
app.run()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 3.传参数/自定义正则参数
- @app.route('/user/
') - @app.route('/post/int:post_id')
- @app.route('/post/float:post_id')
- @app.route('/post/path:path')
- @app.route('/login', methods=['GET', 'POST'])
常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}
2
3
4
5
6
7
8
9
上面的5种类型有时候满足不了需求,所以就有了自定义路由
a.编写自定义路由匹配规则,并把新添加的规则放入url_map中
# 1
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中的参数(val:是方向生成url的值)
@app.route('/index/<xxx("\\d+"):nid>', methods=['GET', 'POST'])
def index(nid):
print(nid, type(nid))
v = url_for('index', nid=999) # /index/999
print(v)
return "Index"
:param value:
:return:
"""
val = super(RegexConverter, self).to_url(value)
return val
# 2
app.url_map.converters['xxx'] = RegexConverter
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 4.@app.route和app.add_url_rule参数
rule, # URL规则
view_func, # 视图函数名称
defaults=None, # 默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数(当需要给视图函数提供参数的时候)
@app.route('/index',defaults={'k':'123'})
def index(k):
print(k) # 123
endpoint=None, # 名称,用于反向生成URL,即: url_for('名称','参数')
methods=None, # 允许的请求方式,如:["GET","POST"]
strict_slashes=None, # 对URL最后的 / 符号是否严格要求,(django中一样)
如:
@app.route('/index',strict_slashes=False),
访问 <http://www.xx.com/index/> 或 <http://www.xx.com/index均可>
@app.route('/index',strict_slashes=True)
仅访问 <http://www.xx.com/index>
redirect_to=None, # 重定向到指定地址 当访问/index的时候自动跳转到/home路由上面
如:
@app.route('/index/<int:nid>', redirect_to='/home/<nid>') # 重定向到路由
def func(adapter, nid):
return "/home/888"
@app.route('/index/<int:nid>', redirect_to=func) # 重定向到函数
subdomain=None, # 获取子域名访问
# 示例一
app = Flask(__name__)
app.config['SERVER_NAME'] = 'oldboy.com:5000' # 服务器地址
"""
www.baidu.com
aab.baidu.com # 子域名aab,www,通过配置获取到子域名
1、添加服务器配置
app.config['SERVER_NAME'] = 'oldboy.com:5000' # 服务器地址
2、在route中添加subdomain='username'
def func(username) # 接收到子域名
"""
@app.route("/dynamic", subdomain="<username>")
def xxxxxxx(username):
print(username)
return 'xxxxx'
# 示例二
from flask import Flask, views, url_for
app = Flask(import_name=__name__)
app.config['SERVER_NAME'] = 'wupeiqi.com:5000'
@app.route("/", subdomain="admin")
def static_index():
return "static.your-domain.tld"
@app.route("/dynamic", subdomain="<username>")
def username_index(username):
return username + ".your-domain.tld"
if __name__ == '__main__':
app.run()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 3、flask视图中使用装饰器
使用装饰器的时候,添加到路由的下面,并在定义装饰器的时候加上@functools.wraps(func),不加的话会默认返回inner函数(使用name可以查看), 如果直接访问inner,没有访问到原来的index(),order(),就会报错
from flask import Flask, render_template, redirect
app = Flask(__name__)
import functools
"""
使用装饰器的时候,添加到路由的下面,并在定义装饰器的时候加上@functools.wraps(func),不加的话会默认返回inner函数(使用__name__可以查看),
如果直接访问inner,没有访问到原来的index(),order(),就会报错
"""
def wapper(func):
@functools.wraps(func)
def inner(*args, **kwargs):
print('before')
return func(*args, **kwargs)
return inner
@app.route('/xxxx', methods=['GET', 'POST'])
@wapper
def index():
return "Index"
@app.route('/order', methods=['GET', 'POST'])
@wapper
def order():
return "order"
if __name__ == '__main__':
app.run()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 4、视图
# 1. FBV
from flask import Flask, render_template, redirect, views
app = Flask(__name__)
import functools
def wapper(func):
"""装饰器"""
@functools.wraps(func)
def inner(*args, **kwargs):
print('before')
return func(*args, **kwargs)
return inner
# FBV
@app.route('/xxxx', methods=['GET', 'POST'])
@wapper
def index():
return "Index"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2.CBV
# CBV
# 方式一
"""
class IndexView(views.View):
methods = ['GET']
decorators = [wapper, ]
def dispatch_request(self):
print('Index')
return 'Index!'
app.add_url_rule('/index', view_func=IndexView.as_view(name='index1')) # name=endpoint,这里的name就和route(endpoint反向生成一样)
"""
# 方式二
class IndexView(views.MethodView):
methods = ['GET','POST'] # 支持方法
decorators = [wapper, ] # 装饰器
def get(self):
return 'Index.GET'
def post(self):
return 'Index.POST'
app.add_url_rule('/index', view_func=IndexView.as_view(name='index2')) # name=endpoint
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 5、请求和响应
使用时需要导包from flask import request
信息看官网:<https://flask.net.cn/quickstart.html#id14>
from flask import Flask, render_template, redirect, request, jsonify, make_response
app = Flask(__name__)
@app.route('/index', methods=['GET', 'POST'])
def index():
# 请求相关
# request.method 方法名
# request.args 参数
# request.form
# request.cookies cookies
# request.headers 请求头
# request.path 请求路径
# request.files 获取上传文件
# obj = request.files['the_file_name'] # 得到上传文件名
# obj.save('/var/www/uploads/' + secure_filename(obj.filename)) 保存到本地
# request.values
# request.full_path
# request.script_root
# request.url
# request.base_url
# request.url_root
# request.host_url
# request.host
# 响应相关
return "" # 字符串
return json.dumps({}) # 字典
return jsonify({}) # 内置模块自动转成字典
return render_template('index.html', n1=123) # 模板
return redirect('/index') # 重定向
# response = make_response(render_template('index.html')) # 设置返回的cookie,headers等
# response = make_response("xxxx")
# response.set_cookie('key', 'value')
# response.headers['X-Something'] = 'A value'
# response.delete_cookie('key')
# return response
if __name__ == '__main__':
app.run()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 6、模板的使用
Jinja2官网:<http://docs.jinkan.org/docs/jinja2/>
Jinja2基本使用:<https://www.cnblogs.com/ryxiong-blog/articles/11170889.html>
2
1、模板的使用
Flask使用的是Jinja2模板,所以其语法和Django无差别
2、自定义模板方法
Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:
flask可以传递函数
传值:
@app.route('/x1', methods=['GET', 'POST'])
def index():
context = {
'k1': 123,
'k2': [11, 22, 33],
'k3': {'name': 'oldboy', 'age': 84},
'k4': lambda x: x + 1,
'k5': gen_input, # 当前模板才能调用的函数
}
return render_template('index.html', **context)
使用:
<h1>{{k1}}</h1>
<h1>{{k2.0}} {{k2[0]}} </h1>
<h1>{{k3.name}} {{k3['name']}} {{k3.get('name',888)}}</h1>
<h1>{{k4(66)}}</h1>
<h1>{{k5(99)}}</h1>
<h1>{{sbbbbbbb(1,2)}}</h1>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
全局:每个模板都可以使用这个函数
@app.template_global()
def sbbbbbbb(a1, a2):
"""
每个模板中可以调用的函数
:param a1:
:param a2:
:return:
"""
return a1 + a2
2
3
4
5
6
7
8
9
# 7、flask中的session
更多操作示例:<https://www.cnblogs.com/wupeiqi/articles/7552008.html>
除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。
- 设置:session['username'] = 'xxx'
- 删除:session.pop('username', None)
flask中的session继承了字典,所以字典有的方法session都有,flask是把session存入cookies中,本地不存。
a.设置一把盐,和django一样 app.secret_key = 'sadfasdfasdf'
b.对session进行添加获取删除等操作
"""
1. 请求刚刚达到
ctx = RequestContext(...)
- request
- session=None
ctx.push()
ctx.session = SecureCookieSessionInterface.open_session
2. 视图函数
3. 请求结束
SecureCookieSessionInterface.save_session()
"""
from flask import Flask, session
app = Flask(__name__)
app.secret_key = 'sadfasdfasdf'
@app.route('/x1')
def index():
# 去ctx中获取session
session['k1'] = 123
session['k2'] = 123
del session['k2']
return "Index"
@app.route('/x2')
def order():
print(session['k1'])
return "Order"
if __name__ == '__main__':
app.run()
# 1. 请求一旦到来显
# app.__call__
# app.wsgi_app
# app.open_session
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 8、特殊装饰器
常见装饰器详细说明:<http://www.coolpython.net/flask_tutorial/basic/flask-decorator-hook.html>
- @app.before_request 执行视图函数之前(从上到下)
- @app.after_request 执行视图函数之后(从下到上)
- 如果before_request有返回值就不执行后面的视图函数和django类似
其实就是把装饰的函数放入列表中,after_request就列表反转了一下
示例一:
from flask import Flask, render_template, redirect
app = Flask(__name__)
"""
before_reuqest = [xxxxxxxxxx1,xxxxxxxxxx2]
"""
@app.before_request # 视图执行之前
def xxxxxxxxxx1():
print('前1')
@app.before_request
def xxxxxxxxxx2():
print('前2')
"""
after_request = [oooooooo1,oooooooo2]
[oooooooo2,oooooooo1,] reversed(after_request)
"""
@app.after_request
def oooooooo1(response):
print('后1')
return response
@app.after_request
def oooooooo2(response):
print('后2')
return response
@app.route('/x1', methods=['GET', 'POST'])
def x1():
print('视图函数x1')
return "视图函数x1"
if __name__ == '__main__':
# app.__call__ # 最先调用call方法
app.run()
# 前1 前2 视图函数x1 后2 后1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
示例二:
from flask import Flask, render_template, redirect
app = Flask(__name__)
@app.before_request
def xxxxxxxxxx1():
print('前1')
return "不要再来烦我了"
@app.before_request
def xxxxxxxxxx2():
print('前2')
@app.after_request
def oooooooo1(response):
print('后1')
return response
@app.after_request
def oooooooo2(response):
print('后2')
return response
@app.route('/x1', methods=['GET', 'POST'])
def x1():
print('视图函数x1')
return "视图函数x1"
if __name__ == '__main__':
app.__call__
app.run()
# 前1 后2 后1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
示例三:接口校验是否登录
from flask import Flask, render_template, redirect, request, session
app = Flask(__name__)
app.secret_key = 'asdfasdfasdf'
@app.before_request
def check_login():
if request.path == '/login': # 登录不用认证
return None
user = session.get('user_info') # 其他接口需要认证
if not user:
return redirect('/login')
@app.route('/login', methods=['GET', 'POST'])
def login():
return "视图函数x1"
@app.route('/index', methods=['GET', 'POST'])
def index():
print('视图函数x2')
return "视图函数x2"
if __name__ == '__main__':
app.run()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 其他常见的装饰器
@app.before_first_request # 第一次请求
def before_first_request1():
print('before_first_request1')
@app.before_request # 执行视图之前执行从上到下
def before_request1():
Request.nnn = 123
print('before_request1')
@app.after_request # 执行视图之后执行从下到上
def after_request1(response):
print('before_request1', response)
return response
@app.errorhandler(404) # 错误页面装饰器,有错误的时候执行
def page_not_found(error):
return 'This page does not exist', 404
@app.template_global() # 模板装饰器,可以在所有的模板中使用
def sb(a1, a2):
return a1 + a2
@app.template_filter() # 过滤装饰器
def db(a1, a2, a3):
return a1 + a2 + a3
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 9、消息闪现
<https://www.w3cschool.cn/flask/flask_message_flashing.html>
flask 提供了一个非常简单的方法来使用闪现系统向用户反馈信息。1、闪现系统使得在一个请求结束的时候记录一个信息,2、并且在下次(且仅在下一次中)请求时访问它返回信息,并删除掉记录,这通常与布局模板结合使用以公开信息。
Flask 模块包含 flash()** 方法。它将消息传递给下一个请求,该请求通常是一个模板。**
flash(message, category) # 设置
其中,
- message 参数是要闪现的实际消息。
- category 参数是可选的。它可以是“error”,“info”或“warning”。类别可以在访问的时候通过类别去过滤
为了从会话中删除消息,模板调用 get_flashed_messages()。
get_flashed_messages(with_categories, category_filter) # 获取并删除
两个参数都是可选的。如果接收到的消息具有类别,则第一个参数是元组。第二个参数仅用于显示特定消息。
from flask import Flask, session, flash, get_flashed_messages
app = Flask(__name__)
app.secret_key = 'asdfasdfasdf'
@app.route('/x1', methods=['GET', 'POST'])
def login():
flash('我要上向龙1', category='x1')
flash('我要上向龙2', category='x2')
return "视图函数x1"
@app.route('/x2', methods=['GET', 'POST'])
def index():
data = get_flashed_messages(category_filter=['x1'])
print(data)
data = get_flashed_messages(category_filter=['x1'])
print(data,222)
return "视图函数x2"
if __name__ == '__main__':
app.run()
"""
['我要上向龙1', '我要上向龙1']
['我要上向龙1', '我要上向龙1'] 222
[]
[] 222
当访问第二次的时候,就为空了 ,只保存一次,调用得到后就删掉其实就是在内部删掉了session.pop()
用session也可以做就是session.pop
"""
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 10、flask中间件
Flask的中间件的性质,就是可以理解为在整个请求的过程的前后定制一些个性化的功能。
在flask中,在执行app.run()之后,如果有请求来,会执行app.__call__方法
通过中间件的方法可以在请求来时之前与来临之后,即执行app.__call__前后执行其他代码,进行一些生命周期的控制
2
- 当一个请求刚进来时: 1).执行app.call方法 2).然后调用app.wsgi_app方法
- 如上,重新定义了一个Middleware类,而实际上返回的就是原来的wsgi_app,但是此时我们就可以在新定义的类中,定制/扩展某些动作;如print操作
- 另外,新定义的Middleware类的call方法的参数,其实就是environ, start_response这两个参数(原来wsgi_app)的参数
- 由于在wsgi_app这一步,我们拿到的仅有原生的environ,因此我们做的只能是对原生的environ进行操作;request、session这些都不能导出/操作(因为只有执行app.wsgi_app之后才有这些参数、方法)
- *因为我们在中间减重不能利用请求和响应来做一些事情,所以中间件的应用场景不多;但是当我们相对原生environ做操作时,就可以用中间件了;所以一般会采用before_request等方法
from flask import Flask
app = Flask(__name__)
app.secret_key = 'asdfasdfasdf'
@app.route('/x2', methods=['GET', 'POST'])
def index():
return "x2"
class Middleware(object): # 2、
def __init__(self, old_wsgi_app):
"""
服务端启动时,自动执行
:param old_wsgi_app:
"""
self.old_wsgi_app = old_wsgi_app
def __call__(self, environ, start_response):
"""
每次有用户请求道来时
:param args:
:param kwargs:
:return:
"""
print('before')
from flask import session, request
obj = self.old_wsgi_app(environ, start_response) # 还是原来的wsgi方法,我们可以在这前后做一些操作,比如ip黑名单过滤(拿到environ)。! 不能用这些,因为是在wsgi_app返回会才有的request、session
print('after')
return obj
if __name__ == '__main__':
app.wsgi_app = Middleware(app.wsgi_app) # 1、
app.run()
"""
1.执行app.__call__
2.在调用app.wsgi_app方法
"""
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 11、蓝图(django的路由分发)
规范的分发路由,具体看示例
蓝图用于为应用提供目录划分:
小型应用程序:示例 (opens new window)
<https://files.cnblogs.com/files/wupeiqi/pro_flask_简单应用程序目录示例.zip>
大型应用程序:示例 (opens new window)
<https://files.cnblogs.com/files/wupeiqi/pro_flask_大型应用目录示例.zip>
其他:
- 蓝图URL前缀:xxx = Blueprint('account', name,url_prefix='/xxx')
- 蓝图子域名:xxx = Blueprint('account', name,subdomain='admin')
前提需要给配置SERVER_NAME: app.config['SERVER_NAME'] = 'wupeiqi.com:5000 (opens new window)'
访问时:admin.wupeiqi.com:5000/login.html (opens new window)
# 12、补充
# 1.生成项目依赖的方式
方式一:
pip3 install pipregs
- 生成依赖文件:pipregs ./ # 执行会会在根目录生成一个requirement.txt文件
- 安装依赖文件 pip instlal -r requirement.txt
2
3
4
方式二:
生成依赖文件:pip freeze > requirements.txt
安装依赖文件:pip instlal -r requirements.txt
2
# 13、函数/方法
from types import MethodType, FunctionType
class Foo(object):
def fetch(self):
pass
# 对象名.方法名 函数
print(isinstance(Foo.fetch, MethodType))
print(isinstance(Foo.fetch, FunctionType)) # True
# 对象.方法名 方法
obj = Foo()
print(isinstance(obj.fetch, MethodType)) # True
print(isinstance(obj.fetch, FunctionType))
2
3
4
5
6
7
8
9
10
11
12
13
14
← 排序 flask基础(2)→