❥Flask❥----介绍

Flask简介

  Flask是一个python编写的轻量级 Web 框架. 其中 WSGI 采用 Werkzeug 魔板语法使用Jinja2 的 同步框架

安装

pip install flask==1.1.1

  下载好后他会自动安装 Werkzeug 和 jinja2

Flask的简单使用

  使用3句代码来启动一个 Flask服务

# Flask模块的导入
from flask import Flask

# 实例化Flask得到 app 对象
app = Flask(__name__) # 声明当前执行目录

# 启动flask
app.run()

   升级版

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()

 配置文件

  不急 先来了解下flask的配置文件

   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.debug
= True app.secret_key = '123' # 方式二 以字典的形式 app.config['DEBUG'] = True # 方式三 以文件的形式 app.config.from_pyfile('settings.py') # 自己写py文件 # 方式四 以类的形式(推荐) app.config.from_object('settings.DevelopmentConfig')

.......

   使用类的形式 类的写法

# DEBUG = True

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

 Flask必会三板斧

from flask import Response,redirect, render_template
# Response 响应数据
# redirect 重定向
# render_template 提供html页面
app = Flask(__name__)

@app.route('/response')
def response():
    return Response('我是response返回的')


@app.route('/redirect')
def redirec():
    return redirect('/response')


@app.route('/render')
def render():
    return render_template('text.html', name='sjjsjss') # 可以传参数  支持魔板语法 和python的一模一样


if __name__ == '__main__':
    app.run(debug=True)

 

 外送两板斧 flask的小儿子

jsonify

@app.route('/json')
def json():
    name_list = [{'name': "jason-gdx"},{'name': "tank-sb"}]
    res = jsonify(name_list)
    print(res)
    return jsonify(name_list) # application/json
发的直接是文件

@app.route('/file')
def file():
    return send_file('templates/text.html') # 自动转content-type

 request

from flask import request
@app.route('/login', methods=['POST', 'GET']) # 可以在app.route里面指定 methods
def login():
    # 导入模块request 我们这里来一一获取里面的数据
    # 判断request里面的提交方法
    if request.method == 'GET':
        return render_template('login.html')
    print(request.method) # POST
    print(request.data) # b'' 没有指定cont-type的 数据
    print(request.json) # None
    print(request.url) # http://127.0.0.1:5000/login?adfadsf=asdfasdf
    print(request.path) # /login
    print(request.headers) #
    print(request.values) # get 和 post 提供的所有值  用来查看数据 CombinedMultiDict([ImmutableMultiDict([('adfadsf', 'asdfasdf')]), ImmutableMultiDict([('user', '123123'), ('password', '123123123')])])
    print(request.form) # 提供方法 to_dict ImmutableMultiDict([('user', '123123'), ('password', '123123123')])
    print(request.host_url) # http://127.0.0.1:5000/
    print(request.host) # 127.0.0.1:5000
    print(request.args) # 提供方法 to_dict get 的值 ImmutableMultiDict([('adfadsf', 'asdfasdf')])

    print(request.files) # 文件
    # 文件获取
    my_file = request.files.get('my_file')
    my_file.save(my_file.filename)

    print(request.cookies) # 他也是字典

 

Flask路由函数

@app.route('/loign', methods=['POST', 'GET'], endpoint='sb')
def login():
    return 'OK'

 

   在路由函数中 @app.route 可以填 url(路由)  methods 请求方式  以及 endpoint 这个是起别名 而且endpoint不能重复!

  同时 我们也可以不使用@app.route 使用 add_url_rule 如何使用?

# @app.route('/loign', methods=['POST', 'GET'], endpoint='sb')
def login(nid):
    print(type(nid))
    # 使用 url_for 来指定url 
    # res_url = url_for('login') # 这里直接指向login函数
    res_url = url_for('sb') # 或者直接用别名来获取到路由
    print(res_url)
    return 'OK'


# 我们这里 使用endpoint 起别名 为sb 
app.add_url_rule('/login/<string:nid>',view_func=login, endpoint='sb', methods=['POST', 'GET'])

   也就是说url_for 是用来获取url的 如果有别名的话 他就指向起了别名的视图函数  

  然我们来研究它内部的 源码吧!

   首先我们先来看看route里面的代码  源码加注释了

    # 传入参数 rule 其实就是url 和 options 就是 methods endpoint viewfunc等
   # self 就是 Flask 实例化的对象 def route(self, rule,
**options):
        #  装饰器呢 f就是你下面的视图函数
        def decorator(f):
            #  获取 option中有没有 endpoit 没有的话就 设置为None
            endpoint = options.pop("endpoint", None)
            #  4 然后调用 add url rule 将参数一一传入
            self.add_url_rule(rule, endpoint, f, **options)
            #  5 最后返回f 执行view func
            return f

        # 1 我们发现这是一个装饰器 直接将decorator返回
        return decorator

 

   然后点进add_url_rule 

 

    @setupmethod
    def add_url_rule(
        self,
        rule,
        endpoint=None,
        view_func=None,
        provide_automatic_options=None,
        **options
    ):

        # 判断endpoint是否为none
        if endpoint is None:
            # 如果是none的话 执行_endpoint_from_view_func 方法 并且将viewfunc传入
            # 拿到名字 为函数名
            endpoint = _endpoint_from_view_func(view_func)
        # 如果不为空的话 那么设置 option中的endpoint 为 endpoint
        options["endpoint"] = endpoint
        # 获取 methods中的 提交方式
        methods = options.pop("methods", None)


def _endpoint_from_view_func(view_func):
    # 断言 如果 viewfunc 为none 的话 那么 报错信息
    assert view_func is not None, "expected view func if endpoint is not provided."
    # 否则 获取 viewfunc函数的__name__ 返回
    return view_func.__name__


 # 然后这里判断method是否为none
        if methods is None:
            # 如果为none 的 话 就直接 使用反射 来获取 viewfunc中的methods 或者 直接默认为 get
            methods = getattr(view_func, "methods", None) or ("GET",)

        # 判断method是否为 字符
        if isinstance(methods, string_types):
            raise TypeError(
                "Allowed methods have to be iterables of strings, "
                'for example: @app.route(..., methods=["POST"])'
            )

        # 使用set来去重 并且大写
        methods = set(item.upper() for item in methods)

        # 使用set来去重 并且大写
        required_methods = set(getattr(view_func, "required_methods", ()))

 

   剩下的源码就是各种处理

  这就是为什么 默认为get 和 可以 使用endpoint来重命名

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

posted @ 2019-11-11 19:33  LD_Dragon  阅读(281)  评论(0编辑  收藏  举报