flask之请求与响应、闪现(阅后即焚)、请求扩展(before,after)、中间件、LOCAL对象、偏函数、

目录

1.flask请求与响应

from flask import Flask,request,make_response,render_template

app = Flask(__name__)




@app.route('/login.html', methods=['GET', "POST"])
def login():
    # 请求相关信息
    # request.method  提交的方法
    print(request.method)
    # request.args  get请求提及的数据
    print(request.args)
    # request.form   post请求提交的数据
    print(request.form)
    # request.values  post和get提交的数据总和
    print(request.values)
    # request.cookies  客户端所带的cookie
    print(request.cookies)
    # request.headers  请求头
    print(request.headers)
    # request.path     不带域名,请求路径
    print(request.path)
    # request.full_path  不带域名,带参数的请求路径
    # request.script_root
    # request.url           带域名带参数的请求路径
    # request.base_url      带域名请求路径
    # request.url_root      域名
    # request.host_url      域名
    # request.host          127.0.0.1:500
    # request.files
    # obj = request.files['the_file_name']
    # obj.save('/var/www/uploads/' + secure_filename(f.filename))

    # 响应相关信息
    # return "字符串"
    # return render_template('html模板路径',**{})
    # return redirect('/index.html')
    # return jsonify({'k1':'v1'})

    # response = make_response(render_template('index.html'))

    # response是flask.wrappers.Response类型
    # response.delete_cookie('key')
    # response.set_cookie('key', 'value')
    # response.headers['X-Something'] = 'A value'
    # return response

    #返回字符串
    #response = make_response("内容")
    #response.set_cookie("key","value")

    #返回html
    response=make_response(render_template("index.html"))
    response.headers['X-Something'] = 'sb'
    response.delete_cookie('jason')
    return response


if __name__ == '__main__':
    app.run()

2.闪现

'''
闪现解决的问题:-假设在a页面操作出错,c页面(操作了多少个页面,我不管),跳转到b页面,在b页面显示a页面的错误信息

index页面出现错误,然后在error页面将错误信息抛出,这两个页面之间可以访问多个页面,只要有一次get_flashed_message,那么error就不能打印错误了

'''

from flask import Flask,flash,get_flashed_messages,request
app = Flask(__name__)
#闪现用到session,所以要加上secret_key,否则会报错
app.secret_key = 'dfksdkf'


@app.route('/index')
def index():
    flash('超时错误')
    flash('价格有误', category='price')
    return '这是Index'

@app.route('/error1')
def error1():
    return 'ok'

@app.route('/error')
def error():
    """
    :return:
    """
    data = get_flashed_messages(with_categories=True,category_filter=('price',)) #展示分类名,筛选出分类名叫price的数据
    data2 = get_flashed_messages(with_categories=True) #把分类也取出来。
    data3 = get_flashed_messages() #分类默认是false
    print(data)
    print(data2)
    print(data3)
    #[('price', '价格有误')]
    # [('message', '超时错误'), ('price', '价格有误')]
    # ['超时错误', '价格有误']
    return '这是error'

@app.route('/error2')
def error2():
    # 再取一次就取不到了
    data = get_flashed_messages()

    print('error2', data)

    return '这是error2'

if __name__ == '__main__':
    app.run()

3.请求扩展

from flask import Flask,request,render_template
app = Flask(__name__)

'''
可以多个请求之前的函数
执行顺序是谁在前面谁先执行
如果前面的before_request有返回值,后面的都不会执行
'''
# @app.before_request
# def sb():
#     print(request)
#     print("我是请求之前")
#     return "我是请求之前1的返回"
#
# #上面有返回值,所以这里就不执行了
# @app.before_request
# def  sb1():
#     print("我是请求之前2")
#     #return "我是请求之前2的返回"

#
#
# '''
# 可以在请求之后添加多个after_request
#
# 执行顺序是谁在前面谁后执行(类似于django中间件的响应顺序,也可以理解为栈,后进先执行)
# before_request对我的after_request没有影响,
# 有没有返回值都会执行
#
#
#
#
# '''
# @app.after_request
# def process_response1(response):
#     print('process_response1 走了')
#     return response
#
# @app.after_request
# def process_response2(response):
#     print('process_response2 走了')
#     return response
#
#
# #第一次请求之前打印,之后就不打印了
# @app.before_first_request
# def first():
#    print("我的第一次")

'''
无论有没有异常都会执行,有异常会把异常传递进来

'''

@app.teardown_request
def ter(e):
    print(e) #响应函数里面的a报错:name 'a' is not defined,会被捕捉出来
    print("我是异常")




'''
@app.errorhandler(要捕获的错误码)
'''
@app.errorhandler(500) # 服务器出错,就会传给前台 500错了,可以导一个render_template,渲染一个页面
def error_404(arg):
    print(arg)
    return "500错误了"


#html页面,不用传值就可以直接传过去
@app.template_global()
def sb(a1, a2):
    return a1 + a2


@app.template_filter()
def db(a1, a2, a3):
    return a1 + a2 + a3



@app.route("/")
def index():
    print("我是真的响应函数")
    # a
    return render_template("index.html")




if __name__ == '__main__':
    # app.__call__()
    app.run()

4.中间件

'''
中间件就是在请求来之前和请求走之后加一些东西
在__call__中的self.wsgi_app之前和之后写,不改源码,直接抽出来重写
'''

from flask import Flask,flash,get_flashed_messages,request

app = Flask(__name__)

class MyMiddleware:
    def __init__(self,wsgi_app123):
        self.wsgi_app123=wsgi_app123

    def __call__(self, environ, start_response):

        print("123")
        res=self.wsgi_app123(environ, start_response)
        print("456")
        print(res)
        return res




@app.route('/index')
def index():
    # request.method
    # session['sd']

    return "ssdsdsdfsd"


if __name__ == '__main__':
    #根据__call__里面的 wsgi_app注释部分,写如下模板的中间件,其中,类名(MyMiddleware是可以重命名的,但是与自己重写的类名要一致)
    app.wsgi_app = MyMiddleware(app.wsgi_app) #类加括号,执行__call__方法
    #app.run()本质就是执行app.__call__()
    # run函数里面的run_simple,然后需要传一个参数self对象,这样加括号,就执行了__call__方法
    # app.__call__()
    app.run()

5.LOCAL对象

# 不用local
from threading import Thread
import time
cxw = -1
def task(arg):
    global cxw
    cxw = arg
    time.sleep(2)
    print(cxw) #取出的全是9

for i in range(10):
    t = Thread(target=task,args=(i,))
    t.start()

#
# flask中的request就是存在local对象中的,这样多线程请求的时候就不会乱掉了。
#
# 导入的local
from threading import Thread
from threading import local
import time

特殊的对象
cxw = local()
def task(arg):
    # 对象.val = 1/2/3/4/5
    cxw.value = arg

    time.sleep(2)

    print(cxw.value)#取出的是0-9,且每刷新一次就会重新赋值,不会出现重复数字
for i in range(10):
    t = Thread(target=task,args=(i,))
    t.start()
#
# 字典的形式
# 模拟上面Local对象中不会乱的线程的现象。

from threading import get_ident,Thread
import time
storage = {}
def set(k,v):
    ident = get_ident() #拿到当前线程的线程id
    if ident in storage: #在仓库中就改值,以最新的为准
        storage[ident][k] = v
    else:
        storage[ident] = {k:v} #不在仓库就加进去值
def get(k):
    ident = get_ident()
    return storage[ident][k]


def task(arg):
    set('val',arg)
    time.sleep(2)
    v = get('val')
    print(v)

#在t = Thread 和 set('val', arg)两处打断点,可以看到,循环走完之后,才开始执行任务函数
for i in range(10):
    t = Thread(target=task,args=(i,))
    print(i)
    t.start()

# 面向对象的形式(就是把字典的形式封装成local类,这样使用时生成local对象)

from threading import get_ident,Thread
import time
class Local(object):
    storage = {}
    def set(self, k, v):
        ident = get_ident()
        if ident in Local.storage:
            Local.storage[ident][k] = v
        else:
            Local.storage[ident] = {k: v}

    def get(self, k):
        ident = get_ident()
        return Local.storage[ident][k]
#
obj = Local()
def task(arg):

    obj.set('val',arg)
    v = obj.get('val')
    print(v)
for i in range(10):
    t = Thread(target=task,args=(i,))
    t.start()

# 我们目的是推导出和上面local相同的用法,即对象.val这样,所以就想到.拦截,即__setattr__、__getattr__.
# 下面的代码就是把上面面向对象中的set和get换成__setattr__和__getattr__


from threading import get_ident,Thread
import time
class Local(object):
    storage = {}
    def __setattr__(self, k, v):
        ident = get_ident()
        if ident in Local.storage:
            Local.storage[ident][k] = v
        else:
            Local.storage[ident] = {k: v}
    def __getattr__(self, k):
        ident = get_ident()
        return Local.storage[ident][k]

obj = Local()


def task(arg):
    obj.val = arg
    time.sleep(1)
    print(obj.val)
for i in range(10):
    t = Thread(target=task,args=(i,))
    t.start()

每个对象都有自己的storage

try:
    from greenlet import getcurrent as get_ident
except Exception as e:
    from threading import get_ident
from threading import Thread
from threading import get_ident,Thread
import time
class Local(object):
    def __init__(self): #我们重写了__setattr__,所以这里写了self.storage后,就会调用自己的setattr,然后就调用getattr,一直递归,最后崩掉,故需要调用父类的__setattr__。
        object.__setattr__(self,'storage',{})
        #self.storage={}
    # storage={}

    def __setattr__(self, k, v):
        ident = get_ident()
        if ident in self.storage:
            self.storage[ident][k] = v
        else:
            self.storage[ident] = {k: v}

    def __getattr__(self, k):
        ident = get_ident()
        return self.storage[ident][k]

obj = Local()
obj1=Local()

def task(arg):
    obj.val = arg
    obj.xxx = arg
    print(obj.val)
for i in range(10):
    t = Thread(target=task,args=(i,))
#     t.start()

6.偏函数

from functools import partial
def test(a,b,c,d):
    return a+b+c+d

tes=partial(test,a=1,b=2)

print(tes(c=3,d=4))
# print(tes(3,4))

templates

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
<h1> 我爱我的祖国</h1>
{{sb(1,2)}} <!--直接使用函数-->
{{12|db(1,1)}} <!--直接使用过滤器-->

</body>
</html>

猜你喜欢

转载自www.cnblogs.com/michealjy/p/12050784.html