g对象
### 保存全局变量的g属性:
g:global
1. g对象是专门用来保存用户的数据的。
2. g对象在一次请求中的所有的代码的地方,都是可以使用的。
项目结构:
g_demo.py文件代码:
from flask import Flask,g,render_template,request from utils import login_log app = Flask(__name__) @app.route('/',methods=['GET','POST']) def hello_world(): return 'index' @app.route('/login/',methods=['GET','POST']) def login(): if request.method == 'GET': return render_template('login.html') else: username = request.form.get('username') password = request.form.get('password') if username == 'hyq' and password == '111': #就认为当前这个用户的用户名和密码正确 g.username = 'hyq' g.ip= 'xx' login_log(username) return '恭喜!登录成功' else: return '您的用户名或密码错误' if __name__ == '__main__': app.run(debug=True)
utils.py文件代码:
from flask import g def login_log(username): print ('当前登录用户是:%s' % g.username) def login_ip_log(ip): pass
login.html文件代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="{{ url_for('login') }}" method="post"> <table> <tbody> <tr> <td>用户名:</td> <td><input type="text" placeholder="请输入用户名" name="username"></td> </tr> <tr> <td>密码:</td> <td><input type="text" placeholder="请输入密码" name="password"></td> </tr> <tr> <td></td> <td><input type="submit" value="登录"></td> </tr> </tbody> </table> </form> </body> </html>
钩子函数before_request
主app文件代码:
from flask import Flask,render_template,request,session,url_for,redirect,g import os app = Flask(__name__) app.config['SECRET_KEY'] = os.urandom(24) @app.route('/') def hello_world(): print('index') return 'index' @app.route('/login/',methods=['GET','POST']) def login(): print('login') if request.method =='GET': return render_template('login.html') else: username = request.form.get('username') password = request.form.get('password') if username == 'hyq'and password =='yunqing141': session['username'] = 'hyq' return '登录成功' else: return '用户名或密码错误!' @app.route('/edit/') def edit(): if hasattr(g,'username'): return '修改成功' else: return redirect(url_for('login')) # before_request:在请求之前执行的 # before_request是在视图函数执行之前执行的 # before_request这个函数只是一个装饰器,他可以把需要设置为钩子函数的代码放到视图函数执行之前来执行 @app.before_request def my_before_request(): if session.get('username'): g.username = session.get('username') print('hello world') if __name__ == '__main__': app.run(debug=True)
login.html文件代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> <table> <tr> <td>用户名:</td> <td><input type="text" name="username"></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password"></td> </tr> <tr> <td></td> <td><input type="submit" value="登录"></td> </tr> </table> </form> </body> </html>
1. before_request:
* 在请求之前执行的
* 是在视图函数执行之前执行的
* 这个函数只是一个装饰器,他可以把需要设置为钩子函数的代码放到视图函数执行之前来执行
在以上代码中,my_before_request()函数在视图函数请求执行之前就执行了,因此会把session中的username信息保存到g中,但是需要注意的是,对应前一篇博客对g函数的说明,只要重启服务器,
session.get('username')便得不到'username'的信息了。使用这个钩子函数的好处就在于,可以在视图函数执行之前,就把用户资料在数据库查询的工作完成,减少视图函数中对数据库的访问操作
钩子函数context_processor:
问题:当用户登录以后,不同的页面都需要显示用户信息,例如用户名,这个时候不同的模板,index(登陆前的主页),登录后的页面等等在用户名那个地方就要传入相同的参数,
@app.route('/') def index(): print('index') return render_template('index.html',username="hyq") @app.route('/edit/') def edit(): return render_template('edit.html',username='hyq')
注意,此相应的Html文件已经插入username这个变量,但是这样太麻烦,于是用到了context_processs函数
主app文件代码:
1 from flask import Flask,render_template,request,session,url_for,redirect,g 2 import os 3 4 app = Flask(__name__) 5 app.config['SECRET_KEY'] = os.urandom(24) 6 7 @app.route('/') 8 def index(): 9 print('index') 10 return render_template('index.html') 11 12 @app.route('/login/',methods=['GET','POST']) 13 def login(): 14 print('login') 15 if request.method =='GET': 16 return render_template('login.html') 17 else: 18 username = request.form.get('username') 19 password = request.form.get('password') 20 if username == 'hyq'and password =='yunqing141': 21 session['username'] = 'hyq' 22 return '登录成功' 23 else: 24 return '用户名或密码错误!' 25 26 @app.route('/edit/') 27 def edit(): 28 # if hasattr(g,'username'): 29 # return '修改成功' 30 # else: 31 # return redirect(url_for('login')) 32 return render_template('edit.html') 33 # before_request:在请求之前执行的 34 # before_request是在视图函数执行之前执行的 35 # before_request这个函数只是一个装饰器,他可以把需要设置为钩子函数的代码放到视图函数执行之前来执行 36 37 @app.before_request 38 def my_before_request(): 39 #if session.get('username'): 40 if session.get('username'): 41 g.username = session.get('username',username="hyq") 42 print('有的有的') 43 print('hello world') 44 45 @app.context_processor 46 def my_context_processor(): 47 #username = session.get('username') 48 #if username: 49 return {'username':'hyq'} 50 51 52 if __name__ == '__main__': 53 app.run(debug=True)
注意,此时index和edit函数的返回渲染模板里面,已经不用加上username='hyq'这个变量了,直接由my_context_processor返回值传参,但是这里要小心的是,47行执行的时候并不能得到username,从而return {'username':username}会报错,因为还没有登录,所以47-49行代码可以考虑在数据库中查找username的值
* 上下文处理器应该返回一个字典。字典中的`key`会被模板中当成变量来渲染。
* 上下文处理器中返回的字典,在所有页面中都是可用的。
* 被这个装饰器修饰的钩子函数,必须要返回一个字典,即使为空也要返回。