• Flask_知识点


    模板

    比django中多可以加括号,执行函数,传参数

    from flask import Flask,render_template,Markup,jsonify,make_response
    app = Flask(__name__)
    
    def func1(arg):
        return Markup("<input type='text' value='%s' />" %(arg,))
    @app.route('/')
    def index():
        return render_template('index.html',ff = func1)
    
    if __name__ == '__main__':
        app.run()

    index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        {{ff('六五')}}
        {{ff('六五')|safe}}
    
    </body>
    </html>

    注意:

    1.Markup等价django的mark_safe ,

    2.extends,include一模一样

    jinga2 模板语言

    -支持函数加括号并且传参
      -其它的用法完全同DTL
      -模板中处理:{{ss|safe}}
      -视图函数中用 ss=Markup(ss)
      -有没有处理xss攻击?处理了
        -处理xss攻击
          -html中的特殊符号

    请求响应

       from flask import Flask
        from flask import request
        from flask import render_template
        from flask import redirect
        from flask import make_response
    
        app = Flask(__name__)
    
    
        @app.route('/login.html', methods=['GET', "POST"])
        def login():
    
            # 请求相关信息
            # request.method
            # request.args:get形式提交的参数
            # request.form:post形式提交的参数
            # request.values
            # request.cookies
            # request.headers
            # request.path
            # request.full_path
            # request.script_root
            # request.url
            # request.base_url
            # request.url_root
            # request.host_url
            # request.host
            # 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
            return "内容"
    
        if __name__ == '__main__':
            app.run()

    session

    除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。 (app.session_interface对象)

    设置:session['username'] = 'xxx'
    删除:session.pop('username', None)
    使用必须先设置一下秘钥:app.secret_key='assasadw'
    session['name']='yzy'放值,取值session['name']
    源码执行流程
        --save_session
            --响应的时候,把session中的值加密序列化放到cookie中,返回给浏览器
        --open_session
            --请求来了,从cookie中取出值,反解,生成session对象,以后在视图函数中直接用session就可以了
        --session.modified

    闪现

    -设置:flash('aaa')
    -取值:get_flashed_message()
    -假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息

    示例:

    from flask import Flask,flash,get_flashed_messages,request,redirect
    
    app = Flask(__name__)
    app.secret_key = 'asdfasdf'
    
    
    @app.route('/index')
    def index():
        # 从某个地方获取设置过的所有值,并清除。
        val = request.args.get('v')
        if val == 'oldboy':
            return 'Hello World!'
        flash('超时错误',category="x1")
        return "ssdsdsdfsd"
        # return redirect('/error')
    
    
    @app.route('/error')
    def error():
        """
        展示错误信息
        :return:
        """
        data = get_flashed_messages(category_filter=['x1'])
        if data:
            msg = data[0]
        else:
            msg = "..."
        return "错误信息:%s" %(msg,)
    
    if __name__ == '__main__':
        app.run()
    '''
    闪现
        --使用
            --设置值
                 flash('我出错了')
                 flash('超时错误',category='x1')
            --取值:一旦去过一次,再另一个视图函数中再取就没有了
                 get_flashed_messages()
                 get_flashed_messages(category_filter=['x1','x2'])
            --使用场景:
                --在某个位置放一个值,过会再去取出来
    '''

    请求扩展

    1 before_request

    类比django中间件中的process_request,在请求收到之前绑定一个函数做一些事

    #基于它做用户登录认证
    @app.before_request
    def process_request(*args,**kwargs):
        if request.path == '/login':
            return None
        user = session.get('user_info')
        if user:
            return None
        return redirect('/login')
    -before_request
        @app.before_request
        def before_request():
            print('来了')

    2 after_request

    类比django中间件中的process_response,每一个请求之后绑定一个函数,如果请求没有异常

    @app.after_request
    def process_response1(response):
        print('process_response1 走了')
        return response
    -afer_request
        @app.after_request
        def after_request(response):
            print(type(response))
            print('走了了')
            return response

    3 before_first_request(服务一启动,第一次请求会走,以后再也不走了)

    @app.before_first_request
    def first():
        print('我的第一次')

    4 teardown_request

    每一个请求之后绑定一个函数,即使遇到了异常

    @app.teardown_request
    def ter(e):
        print(e)
        print('无论如何都会走,即便出了异常')

    5 errorhandler

    路径不存在时404,服务器内部错误500

    @app.errorhandler(404)
    def error_404(arg):
        return "404错误了"

    6 template_global

    标签

    @app.template_glob        #标签
    def sb(a1, a2):
        return a1 + a2
        #{{sb(1,2)}}

    7 template_filter

    过滤器

    @app.template_filter()
    def db(a1, a2, a3):
        return a1 + a2 + a3
    #{{ 1|db(2,3)}}

    总结:

    1 重点掌握before_request和after_request,

    2 注意有多个的情况,执行顺序

    3 before_request请求拦截后(也就是有return值),response所有都执行

    中间件(了解)

    -flask中一旦请求到来,要执行app()---->执行的是app.__call__,整个flask的入口
    -代码实现(了解)

    from flask import Flask,session,url_for,redirect,request,flash,get_flashed_messages,render_template
    app = Flask(__name__)
    class MyMiddleWare():
        def __init__(self,my_wsgi_app):
           self.wsgi_app=my_wsgi_app
        def __call__(self, environ, start_response):
            print('之前执行一些东西')
            obj=self.wsgi_app(environ, start_response)
            print('之后执行一些东西')
            return obj
    @app.route('/',methods=['GET','POST'])
    def index():
         return 'ok'
    if __name__ == '__main__':
         app.__call__
         # app.run()
         app.wsgi_app = MyMiddleWare(app.wsgi_app)
         app.run()
         #请求来了,执行app.__call__本质执行的是:self.wsgi_app(environ, start_response),app.wsgi_app(environ, start_response),
         # 会调到自己写的类的__call__方法

    蓝图

    对程序进行目录结构划分

    不使用蓝图,自己分文件

    目录结构:

    -templates
    -views
        -__init__.py
        -user.py
        -order.py
    -app.py

    app.py

    from views import app
    if __name__ == '__main__':
        app.run()

    init.py

    from flask import Flask,request
    app = Flask(__name__)
    #不导入这个不行
    from . import account
    from . import order
    from . import user

    user.py

    from . import app
    @app.route('/user')
    def user():
        return 'user'

    order.py

    from . import app
    @app.route('/order')
    def order():
        return 'order'

    使用蓝图之中小型系统

    目录结构:

    -flask_pro
        -flask_test
            -__init__.py
            -static
            -templates
            -views
                -order.py
                -user.py
         -manage.py 
            

    _init_.py

    from flask import  Flask
    app=Flask(__name__)
    from flask_test.views import user
    from flask_test.views import order
    app.register_blueprint(user.us)
    app.register_blueprint(order.ord)

    manage.py

    from flask_test import  app
    if __name__ == '__main__':
        app.run(port=8008)

    user.py

    from flask import Blueprint
    us=Blueprint('user',__name__)
    
    @us.route('/login')
    def login():
        return 'login'

    order.py

    from flask import Blueprint
    ord=Blueprint('order',__name__)
    
    @ord.route('/test')
    def test():
        return 'order test'
    -使用蓝图划分文件目录
        0 生成蓝图对象
            admin = Blueprint(
                'admin',
                __name__,
                template_folder='templates',
                static_folder='static'
            )
        1 注册蓝图
            -url_prefix访问路由的前缀
            app.register_blueprint(admin, url_prefix='/admin')
        2 使用(只在当前蓝图下有效)
            -注册路由
                @admin.route('/index')
            -请求扩展相关
                @admin.before_request

    请求上下文源码分析

    第一阶段:将ctx(request,session)放到Local对象上
                       
    第二阶段:视图函数导入:request/session 
    request.method
        -LocalProxy对象.method,执行getattr方法,getattr(self._get_current_object(), name)
            -self._get_current_object()返回return self.__local(),self.__local(),在LocakProxy实例化的时候,object.__setattr__(self, '_LocalProxy__local', local),此处local就是:partial(_lookup_req_object, 'request')
    
        -def _lookup_req_object(name):
                top = _request_ctx_stack.top #_request_ctx_stack 就是LocalStack()对象,top方法把ctx取出来
                if top is None:
                    raise RuntimeError(_request_ctx_err_msg)
                return getattr(top, name)#获取ctx中的request或session对象
    
    第三阶段:请求处理完毕
            - 获取session并保存到cookie
            - 将ctx删除

    程序运行,两个LocalStack()对象,一个里面放request和session,另一个放g和current_app

  • 相关阅读:
    freertos 启动任务调度器后卡在svc 0,汇编停在了0x0800014A E7FE B 0x0800014A
    cadence报错:Class must be one of IC, IO, DISCRETE, MECHANICAL, PLATING_BAR or DRIVER_CELL.
    DDR内存256M16、512M8含义
    常用摄像头像素
    cadence报错because the library part is newer than the part in the design cache.Select the part in the cache and choose Design-Update Cache,and then place the part again.
    ESP-Example ble-ancs解析
    ping 请求找不到主机 www.baidu.com
    linux驱动ioctl报[-Werror=incompatible-pointer-types]错
    常用排序算法对比
    修改gitlab服务器网段后修改git配置的方法
  • 原文地址:https://www.cnblogs.com/KrisYzy/p/11844596.html
Copyright © 2020-2023  润新知