学习慕课课程,Flask前后端分离API后台接口的实现demo,前端可以接入小程序,暂时已经完成后台API基础架构,使用postman调试. git
重构部分:
token校验模块
auths认证模块
scope权限模块,增加全局扫描器(参考flask HTTPExceptions模块)
收获我们可以接受定义时的复杂,但不能接受调用时的复杂
如果你觉得写代码厌倦,无聊,那你只是停留在功能的实现上,功能的实现很简单,你要追求的是更好的写法,抽象的艺术,不是机械的劳动而是要创造,要有自己的思考
Sqlalchemy中对类的创建都是用元类的方式,所以调用的时候都不用实例化,当我们重写__init__方法是需要调用orm.reconstrcut装饰器,才会执行实例化对象的构造函数
权限等级模块的设计(api访问权限),如超级管理员,管理员,普通用户,访客,这四者之间的关系,有包含的关系,所以可以考虑合并也可以考虑排除的方式来构建权限控制模块. 参考本项目中的app.libs.scope
学的是解决问题的方法,首先要有深度,在去考虑广度,还要懂得迁移应用,形成自己的思维模型。
知识点复盘 初始化flask应用程序 app = Flask(__name__, static_folder='views/statics', static_url_path='/static', template_folder="templates")创建Flask应用程序实例对象, 如果模块存在,会根据模块所在的目录去寻找静态文件和模块文件, 如果模块不存在,会默认使用app对象所在的项目目录
__name__ 表示以此模块所在的目录作为工作目录,就是静态文等从这个目录下去找
static_folder 指定静态文件存放相对路径 flask默认会用/进行分割然后取最后一个作为访问url 类似Django中的STATICFILES_DIRS
static_url_path 指定访问静态文件的url地址前缀, 类似Django 中的 STATIC_URL
template_folder 指定模板文件的目录
@property def static_url_path(self): """The URL prefix that the static route will be accessible from. If it was not configured during init, it is derived from :attr:`static_folder`. """ if self._static_url_path is not None: return self._static_url_path if self.static_folder is not None: basename = os.path.basename(self.static_folder) return ("http://www.likecs.com/" + basename).rstrip("http://www.likecs.com/") @static_url_path.setter def static_url_path(self, value): if value is not None: value = value.rstrip("http://www.likecs.com/") self._static_url_path = value Flask 中url相关底层类BaseConverter子类:保存提取url参数匹配规则
Rule类:记录一个url和一个视图函数的对应关系
Map类:记录所有url地址和试图函数对应的关系 Map(Rule, Rule, ....)
MapAdapter类:执行url匹配的过程,其中有一个match方法,Rule.match(path, method)
自定义路由管理器 from flask import Flask app = Flask(__name__) from werkzeug.routing import BaseConverter class RegexUrl(BaseConverter): # 指定匹配参数时的正则表达式 # 如: # regex = '\d{6}' def __init__(self, url_map, regex): """ :param url_map: flask会自动传递该参数 :param regex: 自定义的匹配规则 """ super(RegexUrl, self).__init__(url_map) self.regex = regex # 在对应的试图函数之前调用 # 从url中提取出参数之后,会先调用to_python # 会把提取出的值作为参数传递给to_pthon在返回给对应的试图 def to_python(self, value): """可以在这里做一些参数的类型转换""" return value # 调用url_for时会被调用, 用来处理url反向解析时url参数处理 # 返回值用来拼接url def to_url(self, value): """对接收到参数做一些过滤等""" return value # 将自定义路由转换器类添加到转换器字典中 app.url_map.converters['re'] = RegexUrl # 案例 @app.route('/user/<re("[a-z]{3}"):id>') def hello(id): return f'hello {id}' if __name__ == '__main__': app.run(debug=True) 全局异常捕获AOP编程思想,面向切面编程,把事件统一在一个地方处理,在一个统一的出口做处理
errorhandler 在flask 1.0版本之前只支持填写对应的错误码,比如 @app.errorhandler(404)
在flask1.0版本之后就支持全局的异常捕获了@app.errorhandler(code_or_exception),有了这个之后,就可以在全局做一个异常捕获了,不用每个视图函数都做异常捕获。
@app.errorhandler(Exception) def framework_error(e): if isinstance(e, APIException): return e elif isinstance(e, HTTPException): code = e.code msg = e.description error_code = 1007 return APIException(msg, code, error_code) else: if not current_app.config['DEBUG']: return ServerError() else: raise e 异常类型可预知的异常(已知异常)
完全没有意识的异常(未知异常)
abort函数abort(状态码) 是一个默认的抛出异常的方法
调用abort函数可以抛出一个指定状态码对应的异常信息
abort函数会立即终止当前视图函数的运行**
模型对象的序列化