Flask web开发之路十三

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`会被模板中当成变量来渲染。
* 上下文处理器中返回的字典,在所有页面中都是可用的。
* 被这个装饰器修饰的钩子函数,必须要返回一个字典,即使为空也要返回。

 
posted @ 2018-03-28 16:14  嶙羽  阅读(288)  评论(0编辑  收藏  举报