zoukankan      html  css  js  c++  java
  • Flask(一)

    Flask

    0.Flask简介

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

    “微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

    默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用

    wsgiref

    最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。

    如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

    正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块

    from wsgiref.simple_server import make_server

    def mya(environ, start_response):
       print(environ)
       start_response('200 OK', [('Content-Type', 'text/html')])
       if environ.get('PATH_INFO') == '/index':
           with open('index.html','rb') as f:
               data=f.read()

       elif environ.get('PATH_INFO') == '/login':
           with open('login.html', 'rb') as f:
               data = f.read()
       else:
           data=b'<h1>Hello, web!</h1>'
       return [data]

    if __name__ == '__main__':
       myserver = make_server('', 8011, mya)
       print('监听8010')
       myserver.serve_forever()

    wsgiref简单应用

     

    1.安装

    pip3 install flask

    2.werkzeug简介

    Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等

    代码示例:

    from werkzeug.wrappers import Request, Response

    @Request.application
    def hello(request):
       return Response('Hello World!')

    if __name__ == '__main__':
       from werkzeug.serving import run_simple
       run_simple('localhost', 4000, hello)

    3.flask快速使用

    from flask import Flask
    # 实例化产生一个Flask对象
    app = Flask(__name__)
    # 将 '/'和视图函数hello_workd的对应关系添加到路由中
    @app.route('/') # 1. v=app.route('/') 2. v(hello_world)
    def hello_world():
        return 'Hello World!'if __name__ == '__main__':
        app.run() # 最终调用了run_simple()

    4.配置文件

    flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:

     {
            'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
            'TESTING':                              False,                          是否开启测试模式
            'PROPAGATE_EXCEPTIONS':                 None,                          
            'PRESERVE_CONTEXT_ON_EXCEPTION':        None,
            'SECRET_KEY':                           None,
            'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
            'USE_X_SENDFILE':                       False,
            'LOGGER_NAME':                          None,
            'LOGGER_HANDLER_POLICY':               'always',
            'SERVER_NAME':                          None,
            'APPLICATION_ROOT':                     None,
            'SESSION_COOKIE_NAME':                  'session',
            'SESSION_COOKIE_DOMAIN':                None,
            'SESSION_COOKIE_PATH':                  None,
            'SESSION_COOKIE_HTTPONLY':              True,
            'SESSION_COOKIE_SECURE':                False,
            'SESSION_REFRESH_EACH_REQUEST':         True,
            'MAX_CONTENT_LENGTH':                   None,
            'SEND_FILE_MAX_AGE_DEFAULT':            timedelta(hours=12),
            'TRAP_BAD_REQUEST_ERRORS':              False,
            'TRAP_HTTP_EXCEPTIONS':                 False,
            'EXPLAIN_TEMPLATE_LOADING':             False,
            'PREFERRED_URL_SCHEME':                 'http',
            'JSON_AS_ASCII':                        True,
            'JSON_SORT_KEYS':                       True,
            'JSONIFY_PRETTYPRINT_REGULAR':          True,
            'JSONIFY_MIMETYPE':                     'application/json',
            'TEMPLATES_AUTO_RELOAD':                None,
        }

    方式一

       app.config['DEBUG'] = True
       PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)

    方式二

    #通过py文件配置
    app.config.from_pyfile("python文件名称")
    如:
    settings.py
    DEBUG = True
    ​
    app.config.from_pyfile("settings.py")
    #通过环境变量配置
    app.config.from_envvar("环境变量名称")
    #app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])
    环境变量的值为python文件名称名称,内部调用from_pyfile方法
    ​
    app.config.from_json("json文件名称")
    JSON文件名称,必须是json格式,因为内部会执行json.loads
    ​
    app.config.from_mapping({'DEBUG': True})
    字典格式
    ​
    app.config.from_object("python类或类的路径")
    ​
    app.config.from_object('pro_flask.settings.TestingConfig')
    ​
    settings.py
    ​
    ​
    class Config(object):
        DEBUG = False
        TESTING = False
        DATABASE_URI = 'sqlite://:memory:'
    ​
    ​
    class ProductionConfig(Config):
        DATABASE_URI = 'mysql://user@localhost/foo'
    ​
    ​
    class DevelopmentConfig(Config):
        DEBUG = True
    ​
    ​
    class TestingConfig(Config):
        TESTING = True
    ​
    ​
    PS: 从sys.path中已经存在路径开始写
    ​
    PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config为True,则就是instance_path目录(Flask对象init方法的参数)

    5.路由系统

    典型写法

     @app.route('/detail/<int:nid>',methods=['GET'],endpoint='detail')

    默认转换器

    DEFAULT_CONVERTERS = {
       'default':          UnicodeConverter,
       'string':           UnicodeConverter,
       'any':              AnyConverter,
       'path':             PathConverter,
       'int':              IntegerConverter,
       'float':            FloatConverter,
       'uuid':             UUIDConverter,
    }

    路由系统本质

    """
    1. decorator = app.route('/',methods=['GET','POST'],endpoint='n1')
        def route(self, rule, **options):
            # app对象
            # rule= /
            # options = {methods=['GET','POST'],endpoint='n1'}
            def decorator(f):
                endpoint = options.pop('endpoint', None)
                self.add_url_rule(rule, endpoint, f, **options)
                return f
            return decorator
    2. @decorator
        decorator(index)
    """
    #同理
    def login():
        return '登录'
    app.add_url_rule('/login', 'n2', login, methods=['GET',"POST"])
    #与django路由类似
    #django与flask路由:flask路由基于装饰器,本质是基于:add_url_rule
    #add_url_rule 源码中,endpoint如果为空,endpoint = _endpoint_from_view_func(view_func),最终取view_func.__name__(函数名)

    基本用法总结:

    启动flask
    第一步
    from flask import Flask
    app=Flask(__name__)
    第二步
    @app.route("/")
    def index():
        return "123"
    第三步
    app.run()
    
    启动flask本质是执行
    wsgi_app(ev,re)
    
    
    django四剑客
    '''
    redirect--->redirect
    HttpResponse---->""
    render--->render_template 注意他的传值,必须字典打散
    JsonResponse--->jsonify
    '''
    
    配置文件的四种方式
    #第一种方式
    # app.debug=True
    # app.secret_key="asdas"
    #第二种方式
    # app.config["DEBUG"]=True
    #第三种方式
    # app.config.from_pyfile("settings.py")
    #第四种方式(推荐)
    app.config.from_object('settingss.Test')
    
    flask路由本质
    基于装饰器添加路由其实是执行:
    app.add_url_rule(self, rule, endpoint=None, view_func=None)
    rule--->路由
    endpoint--->反向解析的别名
    view_func---->当前的视图函数
    methods ---->允许请求的方式["get","post"],如果不传默认允许的是get请求
    
    怎样反向解析获取路由
    url_for(别名)

    严格模式:

    from flask import Flask
    app=Flask(__name__)
    
    @app.route("/<int:nid>",strict_slashes=False)
    def index(nid):
        print(nid)
        return "ok"
    
    
    @app.route("/index",strict_slashes=True,redirect_to="/1")
    def index1():
    
        return "ok1"
    
    if __name__ == '__main__':
        app.run()

    CBV(源码分析)

    '''
    def
    auth(func): def inner(*args, **kwargs): print('before') result = func(*args, **kwargs) print('after') return result ​ return inner '''​
    方式一:
    class IndexView(views.View): methods = ['GET'] # decorators = [auth, ] ​ def dispatch_request(self): print('Index') return 'Index!' #如果不传name,这所有返回的都是view,这样就会报错,所有人家必须你要传递参数 #然后他传递给view_func的其实就是你视图类中的dispatch_request方法。这样我们没有办法,在一个视图类中写多种请求方式 app.add_url_rule('/index', view_func=IndexView.as_view(name='index')) # name=endpoint #或者,通常用此方式
    方式二:
    class IndexView(views.MethodView): methods = ['GET'] #cbv添加装饰,用这个,我们看as_view中就知道了,不写methods默认为GET请求 decorators = [auth, ] ​ def get(self): return 'Index.GET'def post(self): return 'Index.POST' #如果我们继承了MethodView,他帮我们重写了,dispatch_request方法,他给我们做了一个分发,通过请求,来执行不同的函数 app.add_url_rule('/index', view_func=IndexView.as_view(name='index')) # name=endpoint

    app.add_url_rule参数

    @app.route和app.add_url_rule参数:
    rule, URL规则
    view_func, 视图函数名称
    defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}
    为函数提供参数
    endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
    methods = None, 允许的请求方式,如:["GET", "POST"]
    #对URL最后的 / 符号是否严格要求
    strict_slashes = None
        '''
            @app.route('/index', strict_slashes=False)
            #访问http://www.xx.com/index/ 或http://www.xx.com/index均可
            @app.route('/index', strict_slashes=True)
            #仅访问http://www.xx.com/index
        '''
    #重定向到指定地址
    redirect_to = None, 
        '''
            @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
        '''#子域名访问
    subdomain = None, 
        '''
        #C:WindowsSystem32driversetchosts
        127.0.0.1       www.liuqingzheng.com
        127.0.0.1       admin.liuqingzheng.com
        127.0.0.1       buy.liuqingzheng.com
        
        from flask import Flask, views, url_for
        app = Flask(import_name=__name__)
        app.config['SERVER_NAME'] = 'liuqingzheng.com:5000'
        @app.route("/", subdomain="admin")
        def static_index():
            """Flask supports static subdomains
            This is available at static.your-domain.tld"""
            return "static.your-domain.tld"
        #可以传入任意的字符串,如传入的字符串为aa,显示为 aa.liuqingzheng.com
        @app.route("/dynamic", subdomain="<username>")
        def username_index(username):
            """Dynamic subdomains are also supported
            Try going to user1.your-domain.tld/dynamic"""
            return username + ".your-domain.tld"
        if __name__ == '__main__':
            app.run()
            
        访问:
        http://www.liuqingzheng.com:5000/dynamic
        http://admin.liuqingzheng.com:5000/dynamic
        http://buy.liuqingzheng.com:5000/dynamic
        '''

    支持正则

    #1 写类,继承BaseConverter
    #2 注册:app.url_map.converters['regex'] = RegexConverter
    # 3 使用:@app.route('/index/<regex("d+"):nid>')  正则表达式会当作第二个参数传递到类中
    from flask import Flask, views, url_for
    from werkzeug.routing import BaseConverter
    ​
    app = Flask(import_name=__name__)
    ​
    class RegexConverter(BaseConverter):
        """
        自定义URL匹配正则表达式
        """
        def __init__(self, map, regex):
            super(RegexConverter, self).__init__(map)
            self.regex = regex
    ​
        def to_python(self, value):
            """
            路由匹配时,匹配成功后处理并传递给视图函数中参数的值
            """
            return int(value)
    ​
        def to_url(self, value):
            """
            使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
            """
            val = super(RegexConverter, self).to_url(value)
            return val
    # 添加到flask中
    app.url_map.converters['regex'] = RegexConverter
    @app.route('/index/<regex("d+"):nid>')
    def index(nid):
        print(url_for('index', nid='888'))
        return 'Index'if __name__ == '__main__':
        app.run()

    案例:登录,显示用户信息 (模板)

    from flask import Flask,render_template,request,redirect,url_for,Markup
    app = Flask(__name__)
    app.debug = True
    
    # 模板渲染的时候
    '''
    模板里面
    渲染变量
    {{}}-->和django一样
    {% for k,v in dict.item()%}
        {{v.name}}
        {{v.get("name")}}
        {{v['name']}}
    {% endfor %}
    '''
    '''
    methods=["GET","POST]
    /detail/<int:nid> 
    nid会当做参数传给我们的视图函数
    我们给模板传值的必须是关键字传值
    url_for()做反向解析,填的是endpoint的值,如果要跳转的视图没有指定endpoint,就用函数名
    
    '''
    
    USERS = {
        1:{'name':'张三','age':18,'gender':'','text':"道路千万条"},
        2:{'name':'李四','age':28,'gender':'','text':"安全第一条"},
        3:{'name':'王五','age':18,'gender':'','text':"行车不规范"},
    }
    
    @app.route('/detail/<int:nid>',methods=['GET'])
    def detail(nid):
    
        info = USERS.get(nid)
        return render_template('detail.html',info=info)
    
    
    @app.route('/index',methods=['GET'])
    def index():
    
    
            # return redirect('/login')
        url = url_for('l1')
        return redirect(url)
        #return render_template('index.html',user_dict=USERS)
    
    
    @app.route('/login',methods=['GET','POST'],endpoint='l1')
    def login():
        if request.method == "GET":
            return render_template('login.html')
        else:
            # request.query_string
            user = request.form.get('user')
            pwd = request.form.get('pwd')
            if user == 'cxw' and pwd == '123':
    
                return redirect('http://www.baidu.com')
            return render_template('login.html',error='用户名或密码错误')
    
    def func1(a,b):
        return Markup(f"<h1>蔡徐坤{a},{b}</h1>")
    
    
    
    @app.route("/test")
    def test():
        return render_template('test.html', error=func1)
    
    if __name__ == '__main__':
        app.run()

    templates / detail.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>详细信息 {{info['name']}}...{{info.get('name')}}....{{info.name}}</h1>
        <div>
            {{info.text}}
        </div>
    </body>
    </html>

    index.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>用户列表</h1>
        <table>
            {% for k,v in user_dict.items() %}
            <tr>
                <td>{{k}}</td>
                <td>{{v.name}}</td>
                <td>{{v['name']}}</td>
                <td>{{v.get('name')}}</td>
                <td><a href="/detail/{{k}}">查看详细</a></td>
            </tr>
            {% endfor %}
        </table>
    </body>
    </html>

    login.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>用户登录</h1>
        <form method="post">
            <input type="text" name="user">
            <input type="text" name="pwd">
            <input type="submit" value="登录">{{error}}
        </form>
    </body>
    </html>

    test.html:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Title</title>
    </head>
    <body>
    <!--{{error|safe}}-->
    <!--{{error("666","ttt")}}-->
    <!--<a>{{url_for("l1")}}</a>-->
    1312
    </body>
    </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__)
    
    '''
    获取当前请求的内容
    1 先要导入request
    2 直接用request.方法,属性
    返回的时候,如果需要设置额外的响应参数,比如cookie,heard
    1 response=make_response(四剑客)
    2 response.设置属性=“属性值”
    3 return response
    
    '''
    
    @app.route('/login.html', methods=['GET', "POST"])
    def login():
    
        # 请求相关信息
        # request.method  提交的方法
        print("request.method",request.method)
        # request.args  get请求提及的数据
        print("request.args", request.args)
        # request.form   post请求提交的数据
        # request.values  post和get提交的数据总和
        # request.cookies  客户端所带的cookie
        # request.headers  请求头
        # request.path     不带域名,请求路径
        # request.full_path  不带域名,带参数的请求路径
        # request.script_root
        # request.url           带域名带参数的请求路径
        # request.base_url        带域名请求路径
        # request.url_root      域名
        # request.host_url        域名
        # request.host            127.0.0.1:500
        # 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
        response1=make_response(render_template('rr.html'))
        #response1.set_cookie('key_sss', 'valuessbbsd')              设置cookie
        # response1.delete_cookie('key_sss')                         删除cookie
        response1.headers['sb'] = 'asdas'                            设置响应头
        return response1
    
    if __name__ == '__main__':
        app.run()

    rr.html:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Title</title>
    </head>
    <h1>qweqw</h1>
    <body>
    
    </body>
    </html>

    七.session (cookie键可通过配置文件修改,默认是session;value值是一个加密的字典)

    from flask import Flask,session
    
    
    app = Flask(__name__)
    app.debug=True
    app.secret_key="ajsdklas"
    app.config['SESSION_COOKIE_NAME']="session_key"
    # app.session_interface  查看源码
    @app.route("/")
    def index():
        session['name']="sb"
        return "ok"
    
    @app.route("/test")
    def test():
        print(session['name'])
        return "ok1"
    
    if __name__ == '__main__':
        app.run()

    app.session_interface中save_session的参数(设置cookie的参数)

    key, 键
    value='', 值
    max_age=None, 超时时间 cookie需要延续的时间(以秒为单位)如果参数是 None`` ,这个cookie会延续到浏览器关闭为止
    expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
    path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。
    domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。如, domain=".example.com"所构造的cookie对下面这些站点都是可读的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果该参数设置为 None ,cookie只能由设置它的站点读取
    secure=False, 浏览器将通过HTTPS来回传cookie
    httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

    session源码的执行流程

    -save_seesion
        -响应的时候,把session中的值加密序列化放大到了cookie中,返回到浏览器中
    -open_session
        -请求来了,从cookie中取出值,反解,生成session对象,以后再视图函数中直接用sessoin就可以了。

    八.闪现(message)

    -设置:flash('aaa')
    -取值:get_flashed_message()
    -
    -假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息
    from flask import Flask,flash,get_flashed_messages,request,redirect
    
    app = Flask(__name__)
    app.debug=True
    app.secret_key = 'asdfasdf'
    '''
    1 设置flash
        1.1 flash("要传递的值",category="分类的名称"),如果不传默认是message
        本质:session['_flash']
    2取flash设置的值我们用get_flashed_messages
     2.1 get_flashed_messages(with_categories=False, category_filter=()),
        2.1.1如果不传递 category_filter,取出上面存储的所有分类传递的值
        2.1.2如果不传with_categories就只取值,不取分类的名字,如果传,就获取 分类名和分类值
        
    3 这个flash只能一个视图函数中取,只要有一个视图函数取过了,那其他视图函数就不能获取
        本质:session.pop("_flash")
        3.1 但是在同一个视图函数里面可以无限的取值
       
    
    
    '''
    
    @app.route('/index')
    def index():
        # 从某个地方获取设置过的所有值,并清除。
        #flash('超时错误',category="x1")
        flash("它过来了,你要小心")
        flash("我是第二个",category="ss")
        return "ssdsdsdfsd"
        # return redirect('/error')
    
    
    @app.route('/error')
    def error():
        """
        展示错误信息
        :return:
        如果get_flashed_messages(with_category=True)
        """
        #data = get_flashed_messages(category_filter=['x1'])
        data=get_flashed_messages(with_categories=True,category_filter=['ss'])
        data1 = get_flashed_messages(with_categories=True, category_filter=['ss'])
        print(type(data))
        print(data1)
        return "错误信息:%s" %(data,)
    
    
    if __name__ == '__main__':
        app.run()

     九.请求扩展

    from flask import Flask,render_template
    
    app = Flask(__name__)
    '''
    1 before_request 请求之前
        1.1可写多个befor_request函数
        1.2而且是从上往下执行的
        1.3 一旦有返回值,请求的视图函数不会执行,已经剩下的befor_request不会执行
    2 after_request 请求之后
        2.1可以写多个after_request函数
        2.2 所有的after_request是从下往上执行,和befor_request相反
        2.3 无论 befor_request有没有返回值,我的after_request都会执行
        2.4 必须接受response,而且必须返回response
        
    3 before_first_request 是我项目启动后,接受到的第一个请求,会执行该函数,后面就不会在执行
    
    4 teardown_request(e)
        4.1 这是e 是接收我服务器抛出的异常
        4.2 无论我服务器有没有错误,都会执行该函数
        4.3 虽然能接收异常,但是没有办法处理异常
        
    5 errorhandler(500) 
        5.1 参数的中值为错误码
        5.2 当服务器抛出对应状态码的异常,就会执行该函数
        5.3 并且该函数可以处理异常,让用户无法感知,服务器错误
        5.4 每一个错误码,都需要一个对应的函数进行处理
    
    '''
    
    
    # app.debug=True
    
    
    
    #基于它做用户登录认证
    # @app.before_request
    # def process_request():
    #     print(request)
    #     print("我是请求之前")
    #     return "我回来了"
    #
    # @app.before_request
    # def process_request1():
    #     print("我是请求之前1")
    
    #请求之后
    # @app.after_request
    # def process_response1(response):
    #     print('process_response1 走了')
    
    #     return response
    # @app.after_request
    # def afr(response):
    #     print("23423")
    #     return response
    # @app.after_request
    # def tt(response):
    #     print("我是第一个")
    #     return response
    
    #项目接收的第一个请求
    # @app.before_first_request
    # def a():
    #     print("我的第一次")
    
    #如论有无异常都执行,如果没有异常这个e就是None
    # @app.teardown_request
    # def ter(e):
    #     # if e:
    #         #logingh
    #     # return "wo si l"
    #     print("我抛异常")
    #
    # #我不希望看到我的服务器错误,参数填写的是错误状态码
    # @app.errorhandler(500)
    # def error_500(arg):
    #     print(arg)
    #     return "请等一下在试"
    #
    # @app.errorhandler(404)
    # def erros(arg):
    #     print(arg)
    #     return "你拨打的用户不存在"
    
    @app.template_global()
    def sb(a1, a2):
        return a1 + a2
    
    @app.template_filter()
    def db(a1, a2, a3):
        print(a1)
        print(a2)
        print(a3)
        return a1 + a2 + a3
    #
    
    @app.route('/')
    def index():
        print("我是你要请求的函数")
        # a
        return render_template("gllo.html")
    
    
    
    
    if __name__ == '__main__':
        app.run()

    gllo.html:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Title</title>
    </head>
    <body>
    {{sb(1,2)}}
    {{ 1|db(2,3)}}
    </body>
    </html>

    十.中间件:

    from flask import Flask
    app=Flask(__name__)
    class MyMiddleware:
        def __init__(self,wsgi_app):
            self.wsgi_app_old=wsgi_app
        def __call__(self,environ, start_response):
            print("我的开始之前")
            res=self.wsgi_app_old(environ, start_response)
            print("我是所有的结束之后")
            return  res
    
    @app.before_request
    def a():
        print("我是请求之前")
    
    
    @app.route("/")
    def index():
        print("我是视图函数")
        return "ok"
    
    if __name__ == '__main__':
        app.__call__
        '''
            def __call__(self, environ, start_response):
                print(ww)
                return self.wsgi_app(environ, start_response)
                print(asdas)
                
                
                print(ww)
                return self.wsgi_app(environ, start_response)
                print(asdas)
        
        '''
        app.wsgi_app = MyMiddleware(app.wsgi_app)#MyMiddleware的对象
        #新的app.wsgi_app
        #app.wsgi_app是MyMiddleware的对象
        #app.wsgi_app()
        #MyMiddleware的对象的__call__()
        #MyMiddleware.__call__
    
        app.run()

     

  • 相关阅读:
    记录-java(jxl) Excel导入数据库
    记录--Gson、json转实体类、类转json
    记录--java获取网络资源(图片、音频等)保存本地
    记录--指定路径复制文件到另一个路径
    记录-java执行请求的URL
    记录-Hibernate+servlet实现简单的增、删、查、改
    我的学习之路_第二十八章_JQuery 和validator插件
    我的学习之路_第二十七章_jQuery
    我的学习之路_第二十六章_javaScript(2)
    我的学习之路_第二十五_javaScript
  • 原文地址:https://www.cnblogs.com/sima-3/p/11600539.html
Copyright © 2011-2022 走看看