视图示例
@app.route('/hello') def hello(): return 'Hello World' if __name__ == '__main__': app.run()
特殊的装饰器
1. before_request # 在所有视图函数执行前执行 2. after_request # 在所有视图函数执行后执行 示例: from flask import Flask app = Flask(__name__) @app.before_request def x1(): print('before:x1') return '滚' @app.before_request def xx1(): print('before:xx1') @app.after_request def x2(response): print('after:x2') return response @app.after_request def xx2(response): print('after:xx2') return response @app.route('/index') def index(): print('index') return "Index" @app.route('/order') def order(): print('order') return "order" if __name__ == '__main__': app.run() 3. before_first_request # 在视图函数第一次执行之前执行,只执行一次 from flask import Flask app = Flask(__name__) @app.before_first_request def x1(): print('123123') @app.route('/index') def index(): print('index') return "Index" @app.route('/order') def order(): print('order') return "order" if __name__ == '__main__': app.run() 4. template_global # 定义全局的函数 可以被任意模板调用 5. template_filter # 定义一个模板filter 6. errorhandler # 页面错误的时候会执行此函数 @app.errorhandler(404) def not_found(arg): print(arg) return "没找到"
给视图函数加装饰器的注意事项
如果按照正常的写法直接在视图函数上加装饰器@wrapper,则会报错,这是因为加完装饰器之后,原函数名就改变了。
报错信息:
AssertionError: View function mapping is overwriting an existing endpoint function: inner
在@app.route的情况下增加装饰器的写法:
from flask import Flask,request,render_template,redirect,session,url_for,views from flask import render_template app = Flask(__name__) #实例化flask对象 app.debug = True #能够随时更改自动重启,不加的话每次更改代码需要手动重启 app.config['SECRET_KEY'] = '123456' #secret_key,用于给session加密 @app.route('/login',methods=['GET','POST'],endpoint='t1') #endpoint是url的别名,相当于django中Url的name def login(): if request.method == "GET": # res = request.query_string # print(res) 获取通过GET请求url传过来的参数 return render_template('login.html') else: user = request.form.get('user') pwd = request.form.get('pwd') if user == 'tom' and pwd == '123': session['userinfo'] = user #设置session return render_template('hello.html') return render_template('login.html', error='用户名或密码错误') def wapper(func): def inner(*args,**kwargs): user = session.get('user_info') if not user: return redirect('/login') return func(*args,**kwargs) return inner @app.route('/detail/<int:nid>',methods=['GET'],endpoint='n1') @wapper def detail(nid): print(nid) return render_template('hello.html') ''' 如果给一个视图函数增加装饰器,应该加在app.route下面,这样的效果就是, 装饰器将下面的所有内容包裹,然后路由对应到这大的包裹中来。 需要注意endpoint要注明,如果不注明endpoint则默认用函数名来定义, 此时所有的函数名都叫inner了,所以需要注明endpoint,只是为了区分。 ''' if __name__ == '__main__': app.run()
另一种写法:
import functools def wapper(func): @functools.wraps(func) def inner(*args,**kwargs): return func(*args,**kwargs) return inner ''' functools.wraps()相当于保留元信息 说白了就是,如果不加这个装饰器,那么你打印detail的__name__它就是inner了, 因为加了装饰器,效果等同于inner=inner(detail()), 如果在装饰器中加了functools这个装饰器,那么相当于给__name__重新赋值,inner.__name__ = func.__name_- 其函数的名字得以保留。 ''' @wapper def detail(): pass print(detail.__name__)
flask的get_flashed_messages,flash
from flask import Flask,get_flashed_messages,flash app = Flask(__name__) app.secret_key = 'asdf' @app.route('/get') def get(): data = get_flashed_messages() print(data) return 'Hello world' @app.route('/set') def set(): flash('info info') ''' 闪现效果,相当于set视图函数执行2次,会在一个列表中存储两个flash函数的内容, 当执行get_flashed_messages的时候则会取出该列表,并清空,类似字典的Pop。 具体用处不大。。。 ''' return 'Hello world' if __name__ == '__main__': app.run()
flash还可以通过category参数给Flash内容归类,通过不同类别取不同内容。