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>