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):
# 2 装饰器呢 f就是你下面的视图函数 def decorator(f): # 3 获取 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来重命名