一.什么是flask?
1.和django一样都是基于python开发的web框架 2.和django一样是同步的框架 3.依赖jinja2模板和Werkzeug WSGI服务的一个微型框架
二.安装flask
pip3 install flask
三.werkzeug简介
Werkzeug是一个基于WSGI的工具包,可以作为一个Web框架的底层库,它封装好了很多Web框架的东西,比如Request,Response
四.flask快速使用
from flask import Flask # 实例化生成一个FLask对象 app = Flask(__name__) # 将'/'和视图函数index绑定,并添加到路由中 @app.route('/') def index(): return 'ok' if __name__ == '__main__': # run()本质是调用了run_simple() app.run()
五.flask基本使用之四剑客
flask可以直接返回字符串,也可以返回html页面,也可以重定向到其他页面,也可以返回json数据
from flask import Flask, render_template, redirect, jsonify app = Flask(__name__) @app.route('/') def index(): # 1.直接返回字符串 # return 'ok' # 2.返回html页面,可以使用模板语法 # dic = {'age': 18} # return render_template("index.html", name='sxc', dic=dic) # 3.重定向页面 # return redirect('/login') # 4.返回json数据 # info = [{'name': 'sxc'}, {'name': 'zzj'}] # return jsonify(info) @app.route('/login') def login(): return 'login' if __name__ == '__main__': app.run()
六.flask配置文件的四种方式
# flask的配置文件 from flask import Flask app = Flask(__name__) # 第一种配置方式,只能配置两种 # app.debug = True # app.secret_key = '123' # 第二种配置,以字典的形式 # app.config['DEBUG'] = True # 第三种,以文件的形式 # app.config.from_pyfile('settings.py') # 第四种,以类的方式(推荐) app.config.from_object('settings.ProductionConfig') @app.route('/index') def index(): print(123) return 'ok' if __name__ == '__main__': app.run()
具体的配置文件
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.route('/index/<int:nid>', methods=['POST', 'GET'], endpoint='hhh')
通过源码分析得到的新方式
app.add_url_rule('/index/<string:nid>', methods=['GET', 'POST'], view_func=index, endpoint='hhh')
路由系统的本质
def decorator(f): endpoint = options.pop("endpoint", None) self.add_url_rule(rule, endpoint, f, **options) return f ''' 内部代码self.add_url_rule(rule, endpoint, f, **options) 这里的self指代的就是app,rule就是/index, f就是index函数 endpoint是为该路由取的别名,不传默认是函数名 view_func就是f就是index, endpoint必须有值,当不传的情况下,默认使用函数名,如果不使用装饰器,并且view_func也不传,那么endpoint就会没有值,那么就会报错 '''
路由中的<string:nid>是它的有名分组,前面的是指定类型,后面的是传入的参数
CBV(源码分析)
# CBV的控制类 from flask import Flask, views app = Flask(__name__) app.debug = True class IndexView(views.View): def dispatch_request(self): print('Index') return 'index' app.add_url_rule('/index', view_func=IndexView.as_view(name='index'), endpoint='hhh') if __name__ == '__main__': app.run() # 内部源码 @classmethod def as_view(cls, name, *class_args, **class_kwargs): def view(*args, **kwargs): self = view.view_class(*class_args, **class_kwargs) return self.dispatch_request(*args, **kwargs) view.view_class = cls # 将控制类赋值给view_class view.__name__ = name # 将name赋值给__name__ view.__doc__ = cls.__doc__ view.__module__ = cls.__module__ view.methods = cls.methods view.provide_automatic_options = cls.provide_automatic_options return view ''' 上面源码的view.__name__ = name十分重要, 因为endpoint必须有值,当不传的时候默认是函数的__name__, 如果这步不设置,那么所有控制类的endpoint就都是view了,这样会出错 所以必须提前设置view.__name__ = name,故而这个name我们必须传入, 当然我们传入name之后还是可以指定endpoint '''
CBV的不同请求方式的不同执行函数
# 自定义的CBV代码 class IndexView(views.MethodView): # decorators = [,,,] # 装饰器,可以有多个 def get(self): return 'index get' def post(self): return 'index post' app.add_url_rule('/index', view_func=IndexView.as_view(name='index'), endpoint='hhh') # 源码,继承MethodView class MethodView(with_metaclass(MethodViewType, View)): def dispatch_request(self, *args, **kwargs): meth = getattr(self, request.method.lower(), None) # 如果没传默认是get方法 if meth is None and request.method == "HEAD": meth = getattr(self, "get", None) assert meth is not None, "Unimplemented method %r" % request.method # 传了就是对应的方法,即meth=get/post # 下面加括号调用之后就执行自定义函数对应的方法 return meth(*args, **kwargs)
app.add_url_rule参数
from flask import Flask app = Flask(__name__) app.debug = True # strict_slashes该参数是用来设置严格模式,当设置为False时/index和/index/都可以被识别 # redirect_to是路由跳转 @app.route('/index', strict_slashes=False, redirect_to='/login') def index(): return 'index' @app.route('/login/<int:nid>') def login(nid): print(nid) return 'login' if __name__ == '__main__': app.run()
@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.导入from werkzeug.routing import BaseConverter 2.写一个类继承BaseConverter,初始化实现__init__方法,实现to_python和to_url两个函数 3.app.url_map.converters['regex'] = RegexConverter添加到flask中 4.绑定的装饰器@app.route('/index/<regex("d+"):nid>'),书写注册的正则 5.regex正则匹配出的结果交给to_python,进行一系列自定义操作后return出来 6.当我们做反向解析的时候,参数传给to_url,return才是我们需要拼接到路由上的 ''' from flask import Flask, views, url_for from werkzeug.routing import BaseConverter app = Flask(__name__) class RegexConverter(BaseConverter): ''' 自定义url匹配正则表达式 ''' def __init__(self, map, regex): super().__init__(map) self.regex = regex def to_python(self, value): ''' 路由匹配时,匹配成功后传递给视图函数中参数的值 ''' return int(value) def to_url(self, value): ''' 使用url_for反向生成url时,传递的参数经过该方法处理,返回的值用于生成url中的参数 ''' val = super().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=nid)) return 'index ok' if __name__ == '__main__': app.run()
89