• flask


    知识点

    1.谈谈你对django和flask的认识。

    2.flask和django最大的不同点:request/session

    session的存储方式不同

    django 存放在数据库      flask 存放在cookie里面

    中间件不同

    django 有许多内置的, flask 需要自己写


    - 给你一个路径 “settings.Foo”,可以找到类并获取去其中的大写的静态字段。
    
        settings.py
            class Foo:
                DEBUG = True
                TEST = True
    
        xx.py
            import importlib
    
            path = "settings.Foo"
    
            p,c = path.rsplit('.',maxsplit=1)
            m = importlib.import_module(p)
            cls = getattr(m,c)
    
            # 如果找到这个类?
            for key in dir(cls):
                if key.isupper():
                    print(key,getattr(cls,key))
    importlib

    1.配置文件


    app.config.from_object("settings.DevelopmentConfig")

                           # setting.py     配置类

    class Config(object):
        DEBUG = False
        TESTING = False
        SECRET_KEY = "asdfasdfas23"
        DATABASE_URI = 'sqlite://:memory:'
    
        # 设置session
        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
        PERMANENT_SESSION_LIFETIME = timedelta(hours=1)
    
    # 其他配置,实现多情景下配置,app.py只需要改对应的配置类
    
    class ProductionConfig(Config):
        DATABASE_URI = 'mysql://user@localhost/foo'
    
    class DevelopmentConfig(Config):
        DEBUG = True
    
    class TestingConfig(Config):
        TESTING = True
    
    setting.py

    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(...)
    
    方式二:
        app.config.from_pyfile("python文件名称")
            如:
                settings.py
                    DEBUG = True
    
                app.config.from_pyfile("settings.py")
    
        app.config.from_envvar("环境变量名称")
            环境变量的值为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目录
    view


    2. 路由系统


    - endpoint,反向生成URL,默认函数名
    - url_for('endpoint') / url_for("index",nid=777)
      #反向解析                               #参数
    - 动态路由:
         @app.route('/index/<int:nid>',methods=['GET','POST'])
         def index(nid):
             print(nid)
             return "Index"

    @app.route('/user/<username>')
    @app.route('/post/<int:post_id>')
    @app.route('/post/<float:post_id>')
    @app.route('/post/<path:path>')
    @app.route('/login', methods=['GET', 'POST'])
    常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:
    
    DEFAULT_CONVERTERS = {
        'default':          UnicodeConverter,
        'string':           UnicodeConverter,
        'any':              AnyConverter,
        'path':             PathConverter,
        'int':              IntegerConverter,
        'float':            FloatConverter,
        'uuid':             UUIDConverter,
    }
    view
    def auth(func):
                def inner(*args, **kwargs):
                    print('before')
                    result = func(*args, **kwargs)
                    print('after')
                    return result
    
            return inner
    
            @app.route('/index.html',methods=['GET','POST'],endpoint='index')
            @auth
            def index():
                return 'Index'
    
            或
    
            def index():
                return "Index"
    
            self.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])
            or
            app.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])
            app.view_functions['index'] = indexdef 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!'
    
            app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpointclass IndexView(views.MethodView):
                methods = ['GET']
                decorators = [auth, ]
    
                def get(self):
                    return 'Index.GET'
    
                def post(self):
                    return 'Index.POST'
    
    
            app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint
    
    
    
    
            @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"]
    
    
                strict_slashes=None,        对URL最后的 / 符号是否严格要求,
                                            如:
                                                @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>')
                                                或
                                                def func(adapter, nid):
                                                    return "/home/888"
                                                @app.route('/index/<int:nid>', redirect_to=func)
                subdomain=None,             子域名访问
                                                    from flask import Flask, views, url_for
    
                                                    app = Flask(import_name=__name__)
                                                    app.config['SERVER_NAME'] = 'wupeiqi.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"
    
    
                                                    @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()
    
    
    a.注册路由原理
    注册路由原理


    3. FBV 视图处理


    4.请求


    from flask import Flask
        from flask import request,render_template,redirect,make_response
    
        app = Flask(__name__)
    
    
        @app.route('/login.html', methods=['GET', "POST"])
        def login():
    
            # 请求相关信息
            # request.method
            # request.args   # get的参数
            # request.form
            # 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')
    
            # 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()
    view


    5. 响应

            响应体:
                return “asdf”
                return jsonify({'k1':'v1'})
                return render_template('xxx.html')
                 return redirect()
             
             定制响应头:   
                obj = make_response("asdf")     
                 obj.headers['xxxxxxx'] = '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)
    
        应用场景:比较少的函数中需要额外添加功能。
    
    版本三:before_request
        @app.before_request
        def xxxxxx():
            if request.path == '/login':
                return None
    
            if session.get('user'):
                return None
    
            return redirect('/login')
    示例程序:认证

    6. 模板渲染


    - 基本数据类型:可以执行python语法,如:dict.get()  list['xx']
    - 传入函数
         - django,自动执行
         - flask,不自动执行 需要加括号 func()
    - 全局定义函数

         多个地方调用的时候,就不用挨个传

    app.py
    @app.template_global()
     def sb(a1, a2):
         # {{sb(1,9)}}
         return a1 + a2
    
    @app.template_filter()
     def db(a1, a2, a3):
         # {{ 1|db(2,3) }}                 # 可以if 判断
        return a1 + a2 + a3
    

    - 模板继承
     layout.html
             <!DOCTYPE html>
             <html lang="zh-CN">
             <head>
                 <meta charset="UTF-8">
                 <title>Title</title>
                 <meta name="viewport" content="width=device-width, initial-scale=1">
             </head>
             <body>
                 <h1>模板</h1>
                 {% block content %}{% endblock %}    #预留的模块
            </body>
             </html>
    
         tpl.html
             {% extends "layout.html"%}
    
            {% block content %}
                 {{users.0}}
             {% endblock %}
    
    - include
         导入子页面
        {% include "form.html" %}
         form.html
             <form>
                 asdfasdf
                 asdfasdf
                 asdf
                 asdf
             </form>
    view
    - 宏

        重复使用模块,方便调用
        定义好的宏
    
    
        {% macro ccccc(name, type='text', value='') %}
            <h1>宏</h1>
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
             <input type="submit" value="提交">
         {% endmacro %}
    
        调用传参(类似函数)
         {{ ccccc('n1') }}
         {{ ccccc('n2') }}
    
    
    view
    - 安全
         - 前端: {{u|safe}}
         - 前端: MarkUp("asdf")


    7. session


    当请求刚到来:flask读取cookie中session对应的值:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95,将该值解密并反序列化成字典,放入内存以便视图函数使用。

    操作的session 是字典。反回的时候将字典序列化,放到cookie反回给用户

    image
    视图函数:
         @app.route('/ses')
         def ses():
             session['k1'] = 123
             session['k2'] = 456
             del session['k1']

            return "Session"   
                 session['xxx'] = 123
                 session['xxx']
                
    当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户cookie中。

    SESSION REFRESH EACH REQUEST=True  在每次(最后)访问的基础时间上向后推移过期时间

                                 False 在第一次访问的基础时间向后推移

    更多session配置在默认配置里面更改

    8. 闪现

    在session中存储一个数据,读取时通过pop将数据移除。

    from flask import Flask,flash,get_flashed_messages
    @app.route('/page1')
    def page1():
    
        flash('临时数据存储','error')
        flash('sdfsdf234234','error')
        flash('adasdfasdf','info')
    
        return "Session"
    
    @app.route('/page2')
     def page2():
         print(get_flashed_messages(category_filter=['error']))
         return "Session"
    

    9. 中间件

    跟django的中间件不一样,需要自己定制

    基本不用,用before_request


    - call方法什么时候出发?
         - 用户发起请求时,才执行。
    - 任务:在执行call方法之前,做一个操作,call方法执行之后做一个操作。

        class Middleware(object):
            def __init__(self,old):
                 self.old = old
    
            def __call__(self, *args, **kwargs):
                 ret = self.old(*args, **kwargs)
                 return ret
    
    
         if __name__ == '__main__':
             app.wsgi_app = Middleware(app.wsgi_app)
             app.run()
    
    对象() 执行__call__方法
    
    class Test(object):
        def __init__(self,name):
            self.name = name
            print('__init__')
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    a = Test('dsd')
    a()
    """
    __init__
    __call__
    """
    
    
    对象() 执行__call__方法

    10. 特殊装饰器


    1. before_request
    
    2. after_request
    
    示例:
        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()
    
    3. before_first_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()
    
    
    4. template_global
    
    5. template_filter
    
    6. errorhandler
    @app.errorhandler(404)
    def not_found(arg):
        print(arg)
        return "没找到"
    view



    flask 在before_request有return 会把after走完

    django 不是        紫色--django

    image


  • 相关阅读:
    php操作apache服务器上的ftp
    win7配置ftp服务
    php访问远程服务器上的文件
    php操作ini配置文件
    php操作redis简单例子
    win7 32位安装php redis驱动
    mysql事务处理
    php使用PDO连接mysql数据库
    远程连接redis
    设置表格td宽度
  • 原文地址:https://www.cnblogs.com/wenyule/p/9952166.html
Copyright © 2020-2023  润新知