Flask入门(一)之消息闪现、请求扩展、中间件、蓝图、上下文管理

上一篇文章>Flask安装及入门操作

一、消息闪现(flash)


1、使用

#!/usr/bin/env python
# coding:utf-8
from flask import Flask, flash, get_flashed_messages
import os
app = Flask(__name__)
app.debug = True
app.secret_key = os.urandom(24)

@app.route('/get')
def get():
    ### 从某个地方获取设置过的所有值,并清除
    data = get_flashed_messages()
    print(data)
    return "get"

@app.route("/set")
def set():
    ### 向某个地方设置一个值
    flash('flash-set')
    return "set ok!!!"

if __name__ == '__main__':
    app.run(host="10.10.10.111")
http://10.10.10.111:5000/get
http://10.10.10.111:5000/set
http://10.10.10.111:5000/get

Flask入门(一)之消息闪现、请求扩展、中间件、蓝图、上下文管理_第1张图片

2、实例

#!/usr/bin/env python
# coding:utf-8
from flask import Flask, flash, get_flashed_messages, request, redirect
import os
app = Flask(__name__)
app.debug = True
app.secret_key = os.urandom(24)

@app.route('/index')
def index():
    val = request.args.get('v')
    if val == '111':
        return "111111"
    ### 实现分类:flash("time out", category='c1')
    flash("time out")
    return redirect('/error')

@app.route("/error")
def error():
    ### data = get_flashed_messages(category_filer=['c1'])
    data = get_flashed_messages()
    if data:
        msg = data[0]
    else:
        msg = None
    return "Error:%s" % (msg,)

if __name__ == '__main__':
    app.run(host="10.10.10.111")
http://10.10.10.111:5000/index?v=111        ###正常访问
http://10.10.10.111:5000/index              ###访问异常,跳转到error页面

二、请求扩展


1、before_request

先执行before_request,可以实现用户认证!!!

#!/usr/bin/env python
# coding:utf-8
from flask import Flask,  request
import os
app = Flask(__name__)
app.debug = True
app.secret_key = os.urandom(24)

@app.before_request
def before_req(*args, **kwargs):
    print('before')

@app.route('/index')
def index():
    return 'index'

@app.route("/req")
def req():
    return "req"

if __name__ == '__main__':
    app.run(host="10.10.10.111")
http://10.10.10.111:5000/index
http://10.10.10.111:5000/req

Flask入门(一)之消息闪现、请求扩展、中间件、蓝图、上下文管理_第2张图片

2、登陆验证(before_request)

#!/usr/bin/env python
# coding:utf-8
from flask import Flask, request, session, redirect, render_template
import os
app = Flask(__name__)
app.debug = True
app.secret_key = os.urandom(24)

@app.before_request
def process_request(*args, **kwargs):
    if request.path == "/login":
        return None
    user = session.get('user_info')
    if user:
        return None
    return redirect('/login')

@app.route('/index')
def index():
    return 'index'

@app.route("/login", methods=['GET', 'POST'])
def login():
    if request.method == "GET":
        return render_template("login.html")
    else:
        user = request.form.get('user')
        pwd = request.form.get('pwd')
        if user == 'dream' and pwd == '1':
            session['user_info'] = user
            return "/index"
        return render_template('login.html')

if __name__ == '__main__':
    app.run(host="10.10.10.111")
[root@python Flask]# vim templates/login.html



    
    


3、after_request

#!/usr/bin/env python
# coding:utf-8
from flask import Flask, request, session, redirect, render_template
import os
app = Flask(__name__)
app.debug = True
app.secret_key = os.urandom(24)

@app.before_request
def process_request(*args, **kwargs):
    print("before")

@app.after_request
def process_response(response):
    print("after")
    return response

@app.route('/index',methods=["GET",])
def index():
    print("index")
    return "INDEX"

if __name__ == '__main__':
    app.run(host="10.10.10.111")
http://10.10.10.111:5000/index

Flask入门(一)之消息闪现、请求扩展、中间件、蓝图、上下文管理_第3张图片

如果2个before_request和after_request,按照写的顺序执行before_request,倒序执行after_request,就算在before_request中进行return了,after_request依然会执行,跟Django的中间件类似!!!

4、定制错误信息

加入到app.py中即可!!!

@app.errorhandler(404)
def error_404(args):
    return "404"

5、template_global和template_filter(模板定制方法)

我们可以实现在HTML页面中通过来调用函数!!!

### 调用方式:{{tg(1,2)}}
@app.template_global()
def tg(a1, a2):
    return a1 + a2

### 调用方式:{{1|tf(2,3)}}    1代表第一个参数
@app.template_filter()
def tf(a1, a2, a3):
    return a1 + a2 + a3

6、before_first_request

第一次链接时需要进行的操作,可用于初始化!!!

@app.before_first_request
def first(*args, **kwargs):
    pass

三、中间件


class Middle(object):
    def __init__(self,wsgi_app):
        self.wsgi_app = wsgi_app
    def __call__(self, environ, start_response):
        print ("before")             ###这里可以自定义一些操作(执行之前)
        res = self.wsgi_app(environ, start_response)
        print ("end")                ###可以自定义结束后操作
        return res
        
if __name__ == "__main__":
    app.wsgi_app = Middle(app.wsgi_app)
    app.run()

四、蓝图


1、自定制蓝图

[root@python Flask]# pwd
/Python/Flask
[root@python Flask]# vim app.py
from Flask.views import app

if __name__ == '__main__':
    app.run(host="10.10.10.111")
[root@python Flask]# mkdir views/
[root@python Flask]# vim views/__init__.py
from flask import Flask
app = Flask(__name__)

from . import login
[root@python Flask]# vim views/login.py
from . import app
@app.route('/login')
def login():
    return "login..."

@app.route('/logout')
def logout():
    return "logout..."

运行后访问:

http://10.10.10.111:5000/login
http://10.10.10.111:5000/logout

2、自带蓝图(小型项目)

(1)查看文件
[root@python Flask]# pwd
/Python/Flask
[root@python Flask]# tree BP/
BP/
├── BP
│   ├── __init__.py
│   ├── statics                  ###用于放css之类的东西
│   ├── templates
│   │   └── login.html
│   └── views
│       ├── login.py
└── run.py
(2)文件内容
[root@python BP]# pwd
/Python/Flask/BP
[root@python BP]# vim BP/__init__.py
#!/usr/bin/env python
# coding:utf-8
from flask import Flask
from .views.login import login1

app = Flask(__name__, template_folder='templates', static_folder='statics', static_url_path='/static')
app.register_blueprint(login1)
[root@python BP]# vim BP/views/login.py
from flask import Blueprint, render_template
### 修改域名,这样访问需要IP/a/login,template_folder要总的templates不存在
#login1 = Blueprint('login1', __name__, url_prefix='/a',  template_folder=' 自定义templates路径')
login1 = Blueprint('login1', __name__)

@login1.route('/login', methods=['GET', 'POST'])
def login():
    return render_template('login.html')
[root@python BP]# vim BP/templates/login.html 



    
    


[root@python BP]# vim run.py
import sys
import os
### 添加环境
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
sys.path.append(rootPath)
from BP import app

if __name__ == '__main__':
    app.run(host="10.10.10.111")

(3)运行并查看结果

[root@python BP]# python run.py
http://10.10.10.111:5000/login

Flask入门(一)之消息闪现、请求扩展、中间件、蓝图、上下文管理_第4张图片

(4)请求扩展

这里以before_request来作为例子!!!

@app.before_request
def before_req(*args, **kwargs):
    print('before')

如果想实现全局的话放入上面的__init__.py中,单个的话放入例login.py中且把app修改为login1!!!

3、自带蓝图(大型项目)

(1)查看文件
[root@python Flask]# pwd
/Python/Flask
[root@python Flask]# tree large_project/
large_project/
├── large_project
│   ├── admin
│   │   ├── __init__.py
│   │   ├── static
│   │   ├── templates
│   │   └── views.py
│   ├── __init__.py
│   └── web
│       ├── __init__.py
│       ├── static
│       ├── templates
│       └── views.py
└── run.py
(2)文件内容
[root@python large_project]# pwd
/Python/Flask/large_project
[root@python large_project]# vim large_project/admin/__init__.py
#!/usr/bin/env python
#coding:utf-8
from flask import Blueprint
admin = Blueprint(
    'admin',
    __name__,
    template_folder='templates',
    static_folder='static',
)
from . import views
[root@python large_project]# vim large_project/admin/views.py
#!/usr/bin/env python
#coding:utf-8
from . import admin

@admin.route('/admin')
def index():
    return 'admin'
[root@python large_project]# vim large_project/web/__init__.py
#!/usr/bin/env python
#coding:utf-8
from flask import Blueprint
web = Blueprint(
    'web',
    __name__,
    template_folder='templates',
    static_folder='static',
)
from . import views
[root@python large_project]# vim large_project/web/views.py
#!/usr/bin/env python
#coding:utf-8
from . import web

@web.route('/web')
def index():
    return 'web'
[root@python large_project]# vim large_project/__init__.py
#!/usr/bin/env python
#coding:utf-8

from flask import Flask
from .admin import admin
from .web import web

app = Flask(__name__)
app.register_blueprint(admin)
app.register_blueprint(web)
[root@python large_project]# vim run.py
import sys
import os
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
sys.path.append(rootPath)
from large_project import app
if __name__ == '__main__':
    app.run(host="10.10.10.111")

(3)运行并查看结果

http://10.10.10.111:5000/admin
http://10.10.10.111:5000/web

Flask入门(一)之消息闪现、请求扩展、中间件、蓝图、上下文管理_第5张图片
Flask入门(一)之消息闪现、请求扩展、中间件、蓝图、上下文管理_第6张图片

五、上下文管理


1、threading.local

threading.local对象,用于为每个线程开盘一块空间来保存它独有的值,但是此方法在Flask中不能支持协程!!!

#!/usr/bin/env python
#coding:utf-8
import threading
local_values = threading.local()

# class C1(object):
#     def __init__(self):
#         self.name = 0
# local_values = C1()

def fun(num):
    local_values.name = num
    import time
    time.sleep(1)
    print(local_values.name, threading.current_thread().name)

for i in range(10):
    th = threading.Thread(target=fun, args=(i,), name="线程%s" %i)
    th.start()

2、自定制threading.local(支持协程)

(1)安装greenlet(协程)
[root@python ~]# wget https://files.pythonhosted.org/packages/f8/e8/b30ae23b45f69aa3f024b46064c0ac8e5fcb4f22ace0dca8d6f9c8bbe5e7/greenlet-0.4.15.tar.gz
[root@python ~]# tar xf greenlet-0.4.15.tar.gz 
[root@python ~]# cd greenlet-0.4.15
[root@python greenlet-0.4.15]# python setup.py install
[root@python greenlet-0.4.15]# python             ###测试
Python 3.6.0 (default, Apr 23 2019, 10:28:46) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import greenlet
(2)threading.local写法
#!/usr/bin/env python
# coding:utf-8
import threading
try:
    from greenlet import getcurrent as get_ident    ###导入协程
except ImportError:
    try:
        from thread import get_ident
    except ImportError:
        from _thread import get_ident

class Local(object):
    def __init__(self):
        self.storage = {}
        self.get_ident = get_ident

    def set(self, k, v):
        ident = self.get_ident()
        origin = self.storage.get(ident)
        if not origin:
            origin = {k: v}
        else:
            origin[k] = v
        self.storage[ident] = origin

    def get(self,k):
        ident = self.get_ident()
        origin = self.storage.get(ident)
        if not origin:
            return None
        return origin.get(k, None)

local_values = Local()
def task(num):
    local_values.set('name', num)
    import time
    time.sleep(1)
    print(local_values.get('name'), threading.current_thread().name)

for i in range(10):
    th = threading.Thread(target=task, args=(i,), name="线程%s" % i)
    th.start()
(3)通过setattr和getattr实现
#!/usr/bin/env python
# coding:utf-8
import threading
try:
    from greenlet import getcurrent as get_ident    ###导入协程
except ImportError:
    try:
        from thread import get_ident
    except ImportError:
        from _thread import get_ident

class Local(object):
    def __init__(self):
        object.__setattr__(self, '__storage__', {})
        object.__setattr__(self, '__ident_func__', get_ident)
        # self.storage = {}
        # self.get_ident = get_ident

    def __setattr__(self, name, value):
        ident = self.__ident_func__()
        storage = self.__storage__
        try:
            storage[ident][name] = value
        except KeyError:
            storage[ident] = {name: value}

    def __getattr__(self, name):
        try:
            return self.__storage__[self.__ident_func__()][name]
        except KeyError:
            raise AttributeError(name)

local_values = Local()
def task(num):
    local_values.name = num
    import time
    time.sleep(1)
    print(local_values.name, threading.current_thread().name)

for i in range(10):
    th = threading.Thread(target=task, args=(i,), name="线程%s" % i)
    th.start()

你可能感兴趣的:(flask,flash,请求扩展,中间件,蓝图,上下文管理,Flask)