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

     
    人生苦短,何不用python
  • 相关阅读:
    Java的native关键字---JAVA下调用其他语言的关键词
    JAVA关键词synchronized的作用
    Ubuntu下安装android studio的时候,无法进入图形界面--/usr/lib/jdk1.8.0_60/jre/lib/i386/libawt_xawt.so: libXtst.so.6: 无法打开共享对象文件: 没有那个文件或目录
    安装XP和Ubuntu双系统问题——Ubuntu安装时无法识别原有系统
    耗时又繁重的SQL诊断优化,以后就都交给数据库自治服务DAS吧!
    阿里云发布政企安全加速解决方案 加码助力政企信息化安全
    Nacos 权限控制介绍及实战
    资深技术专家崮德在阿里管理研发团队的实践和思考
    容灾切换必备——全局流量管理介绍
    MaxCompute管家详解--管家助力,轻松玩转MaxCompute
  • 原文地址:https://www.cnblogs.com/yqpy/p/8664509.html
Copyright © 2020-2023  润新知