• Flask 视图,中间件


    视图

    FBV

    def index(nid):
        
      
    """ 请求相关信息 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.files      # 请求文件 obj = request.files['the_file_name'] obj.save('/var/www/uploads/' + secure_filename(f.filename))
    """
    dic = {"k1":"v1"}
      
    """ 返回响应体的4种形式 字符串 jsonify 模板 跳转 url """

      # return "index"
      # return jsonify(dic)   # return render_template("xxx.html",dic=dic) # 可带数据传递   # return redirect(url_for("index")) #
    跳转通过 url_for 反向解析
      
       """ 定制响应头的时候构造响应体用到 make_response """

      # 如果想设置响应头和回显cookie,就需要用到make_response
      # response = make_response(render_template('index.html'))
      # response = make_response("字符串")
      # response是flask.wrappers.Response类型
      # response.delete_cookie('key')
      # response.set_cookie('key', 'value')
      # response.headers['X-Something'] = 'A value'
      # return response

    from flask import make_response,headers,set_cookie obj = make_response(jsonify(dic)) obj.headers["xxxxx"] = "123" obj.set_cookie("key","value") return obj

    装饰器实现中间件功能

    预备处理视图函数初始状态

    @app.route('/index')
    def index():
        if not session.get('user'):
            return redirect(url_for('login'))
        return render_template('index.html',stu_dic=STUDENT_DICT)

    视图级别加装,比较适用于对少量视图进行处理

    import functools
    def auth(func):
        @functools.wraps(func)
        def inner(*args,**kwargs):
            if not session.get('user'):
                return redirect(url_for('login'))
            ret = func(*args,**kwargs)
            return ret
        return inner
    
    @app.route('/index')
    @auth
    def index():
        return render_template('index.html',stu_dic=STUDENT_DICT)

    全局级别加装

    @app.before_request
    def xxxxxx():
        if request.path == '/login':
            return None
    
        if session.get('user'):
            return None
    
        return redirect('/login')

    除了 before_request 以外还有其他特殊装饰器:

    1. before_request    谁先定义谁先执行
        执行多个 before 的时候如果再中间有返回值,对于after 的执行直接执行最后一次定义的那个
        
    2. after_request    谁后定义谁执行 
    
    3. before_first_request
    
    4. template_global
    
    5. template_filter
    
    6. errorhandler
    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()
    befor/after_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()
    before_first_request 示例
    @app.errorhandler(404)
    def not_found(arg):
        print(arg)
        return "没找到"
    errorhandler 示例

    CBV

    def auth(func):
        def inner(*args, **kwargs):
            result = func(*args, **kwargs)
            return result
        return inner
    
    # 继承自views.MethodView        采用CBV写法时,为了简单,都是采用继承MethodView的方式写的
    class IndexView(views.MethodView):
        # methods = ['POST']  #只允许POST请求访问
        decorators = [auth,]  #如果想给所有的get,post请求加装饰器,就可以这样来写,也可以单个指定
    
        def get(self):   #如果是get请求需要执行的代码
            v = url_for('index')
            print(v)
            return "GET"
    
        def post(self):  #如果是post请求执行的代码
            return "POST"
    
    app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  #name指定的是别名,会当做endpoint使用
    def auth(func):
        def inner(*args, **kwargs):
            print('before')
            result = func(*args, **kwargs)
            print('after')
            return result
        return inner
    
    # 也可以再往上继承自View
    class IndexView(views.View):
        methods = ['GET']
        decorators = [auth, ]
        # 如果继承自View,就需要dispatch_request
        def dispatch_request(self):
            print('Index')
            return 'Index!'
    
    app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint

    文件上传

    客户端

    • 必须要在表单中上传
    • 提交方式必须是 post
    • enctype 属性必须是 multipart/form-data
    <form action="/login" method="post" enctype="multipart/form-data">
        上传文件: <input type="file">
    </form>

    服务端

    文件会上传到缓存区, 通过 request.files 获取上传文件

    拿到返回值可以调用 save , filename 方法

    f = request.file['name']

    # f.save('路径')
    # f.filename # 得到文件原始名称

    f.save('static/' + f.filename) # 如果不存在 static 会报错

    此方法在上传重名文件的时候会覆盖, 因此需要自己设定绝不会重名的方式,比如用时间戳

    中间件

    首先要知道我们利用请求扩展里提供的装饰器也能够做一些中间件的事,我们这里说的是根据flask的源码流程进行自定义方法来实现中间件的操作

    具体流程:

    app.run会执行werkzeug(第三方WSGI模块)中的run_simple方法,继而执行inner方法,继续执行make_server方法,

    make_sever方法就会返回一个BaseWSGIServer对象,主要是起socket,

    当有请求过来时就会触发flask的call方法,继而执行wsgi_app方法

    利用app.run中的wsgi_app方法可以自定义类,定义的_ _call_ _方法里就可以做一些中间件的事

    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def index():
        return 'Hello World!'
    
    class Md(object):
        def __init__(self,old_wsgi_app):
            self.old_wsgi_app = old_wsgi_app
    
        def __call__(self,  environ, start_response):
            print('开始之前')
            ret = self.old_wsgi_app(environ, start_response)
            print('结束之后')
            return ret
    
    if __name__ == '__main__':
        app.wsgi_app = Md(app.wsgi_app)
        app.run()

     

  • 相关阅读:
    常用数列
    sqrt
    树状数组
    hash
    P1102 A-B数对
    codevs 1795 金字塔 2
    P2296 寻找道路
    [USACO16JAN]子共七Subsequences Summing to Sevens
    P3397 地毯
    关于调用&&传址
  • 原文地址:https://www.cnblogs.com/shijieli/p/10354407.html
走看看 - 开发者的网上家园