# ccbflask **Repository Path**: mjinnn/ccbflask ## Basic Information - **Project Name**: ccbflask - **Description**: flask的基础框架,集成migrate、admin、等工具,加入重写定义字段方法(Column()方法)、admin自动识别数据表、备注字段字段等功能。更多功能更待更新中... - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2023-05-04 - **Last Updated**: 2024-05-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ccbflask(cc基础框架) 当前版本:v1.1 ## 简介 使用ccbflask基础框架,可快速进入项目开发,无需在大同小异的基础框架方面消耗太多时间。适合小项目开发 flask的基础框架,集成flask-sqlalchemy、migrate、admin、等工具以及一些项目中常用的小功能, 加入重写定义字段方法(Column()方法)、 admin自动识别数据表、备注字段字段、全局异常处理、请求响应参数处理等功能。 更多功能更待更新中... 注:该基础框架为个人使用和维护,同时集成一些个人习惯的小功能和小技巧。当然,你也可以不使用这些功能 #### cc基础框架能做什么?: 1. 常用模块集成,快速进入开发阶段 2. 文件结构相对固定,易理解,团队开发效率更高(结构借鉴Django风格) 3. 部分方法重构、代码更精简 4. 部署更简单(部署生产环境,Docker部署几行命令搞定) 5. 状态码定义、可快速通过状态码判断问题 6. 请求传参以及相应结果处理更简洁统一 7. 加入逻辑删除、数据恢复更简单 8. 全局异常处理 9. 更多功能优化中... ## 软件架构 #### 文件结构 cc_flask ├- app 业务app,实现逻辑的地方,如果还有一个后台管理系统,复制这个app重命名即可 | ├- admin.py [预留] admin定制文件,暂时没用,后期版本升级加入。 | ├- models.py 数据库模型文件,当前模块中的模型都应该在models中编写 | ├- urls.py 路由文件,当前模块中所有的接口路由都在这里 | ├- views.py 所有的视图函数都在这里 | └- sql.py 如需使用mvc模式,sql语句应该放这里 | ├- cc_flask 这个文件夹给其他app提供基础功能 | ├- __init__.py 初始化Flask app的文件 | ├- admin.py 实现获取所有app的models的文件。 | ├- migrate.py migrate的注册文件,后续更新可以用来升级更多功能 | ├- error_handler.py 全局异常处理,全局异常处理相关的代码可以在这里写,如监听未登录错误,然后在这里返回对应的错误码等 | ├- exception.py 异常类定义,所有的异常类都可以放在这里 | ├- models.py 提供models的基础功能,String()、ForeignKey()等方法 | ├- request_handle.py 提供请求响应方法以及基础类 | └- url.py 总路由表,新模块需要在这里添加路由 | ├- migrations flask-migrate初始化后得到的文件夹,首次应用请删除该文件夹然后初始化自己的文件夹 ├- static 静态文件,admin定制样式存放的地方,其他应用应该把status放在自己app的文件夹中 ├- templates 模板文件,admin定制样式存放的地方,其他应用应该把templates放在自己app的文件夹中 ├- utils 全局使用的类、方法、工具等,存放在这里 ├- config.py 配置文件,所有的配置项都放在这里。 ├- docker-compose.yml docker-compose的配置文件 ├- Dockerfile Docker镜像配置文件 ├- manage.py 启动文件,设置环境变量 FLASK_APP=manage.py,然后python -m flask run 即可启动 ├- README.md 自述文件 ├- uwsgi.ini uwsgi的配置文件,docker启动时使用。 └- requirements.txt 所需依赖文件,建议每次新增依赖时都第一时间添加进去 ## 安装教程 ##### 1. 克隆到本地 ```shell git clone https://gitee.com/mjinnn/ccbflask.git ``` ##### 2. pychar启动(开发推荐、可以使用断点) 1. 在编辑器顶部的 Run/Debug configurations中添加一个flask server 2. target type设为 Script Path,targe设为manage.py绝对路径 3. FLASK_ENV 设置 Dev 或者 development。 4. FLASK_DEBUG 勾选上 5. 保存退出,运行即可 配置如图: ![图片](./docs/images/run_or_debug_configurations.png) ##### 3. 命令行模式启动 1. 设置环境变量 ```shell # linux / macos export FLASK_APP=manage.py export FLASK_ENV=Dev # windows set FLASK_APP=manage.py set FLASK_ENV=Dev ``` 2. 启动程序 ```shell python -m flask run # 或者 flask run ``` ##### 4. docker启动(生产环境推荐使用) 启动方式:flask + docker + uwsgi + nginx 1. 配置数据库, > 方式1:使用docker自动构建数据库(无需另外准备数据库,小项目推荐使用,方便快速,默认带持久化)。 > > 在config.py文件中,将对应环境的DATABASES中的HOST设为db(db是指docker-compose.yml中数据库容器) > 方式2:使用其他数据库(已有数据库,或者自己搭建数据库,更灵活) > > 首先在docker-compose.yml 中注释掉db相关的配置,搜索*db,按照注释内容操作即可。 > 然后在config.py中配置自己的数据库信息即可 2. 环境配置,打开docker-compose文件,修改web里面的FLASK_ENV配置项,根据config.py文件中的类名进行修改,如测试环境:Dev,或生产环境Pro 3. 启动容器,相关命令如下 ```shell # 启动容器命令 docker-compose up -d # 停止容器命令 docker-compose stop # 重启 docker-compose restart # 强制重新创建容器(修改配置文件后重启无效果,可以尝试这个命令) docker-compose up -d --force-recreate # 删除容器 docker-compose rm ``` ## 使用说明 ### 一、新增app #### 1.1、新增文件 把app文件夹整个复制粘贴,改名为你的app名称,如新增后台管理backend,然后将不需要的文件或内容删除即可 #### 1.2、 配置APP config.py文件中,APP列表中添加你的app ``` class Config: # ... 省略其他配置 APP = ['app','backend',...] # backend 就是你app的名称 # 如果没有注册APP,admin以及 migrate工具将无法识别到models ``` #### 1.3、添加路由 打开cc_flask中的urls.py文件,在blueprints中添加路由 ``` blueprints = [api, backend] ``` ### 二、蓝图(路由)使用: ##### 2.1、添加蓝图 在相应的app内的urls.py文件中添加蓝图,实际使用的是官方的Blueprint.add_url_rule,一个例子 : ``` # ...其他代码。 # path方法就是Blueprint.add_url_rule,只是简化了一下。 # 默认GET请求,POST或其他请求要手动加入 methods=['GET', 'POST'] path('/health', view_func=views.health, endpoint='health') path('/index', view_func=views.hello, endpoint='index', methods=['GET', 'POST']) ``` ### 三、CModel使用(模型管理器): CModel是一个拥有更多便捷用法的Model,继承sqlAlchemy的db.Model并在其基础上重写一些了用法,当然,你也可以选择原生方法。具体如下 #### 3.1、一个简单的示例 在sqlAlchemy创建一个表时,我们通常会这样做 ```python from cc_flask.models import db class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, comment="用户id") username = db.Column(db.String(50), comment="用户名称") ``` 这样的写法个人感觉比较麻烦,每次都要Column一下,而且不是很直观,再参考Django,于是乎就有了以下的写法 ```python from cc_flask.models import db, String, Boolean, CModel, ForeignKey, ManyToMany, Integer class Tags(CModel): # 默认带id,create_time 等字段 name = String("标签", max_length=20) class UserGroup(CModel): name = String('分组名', default=True) # 这里可以选择继承models.py里的Model, # 或者你不喜欢自带id等参数,也可以选择sqlAlchemy的Model class User(db.Model): # 这里需要自己定义id字段 id = Integer('id', primary_key=True, autoincrement=True, name='id') username = String(comment="用户名称", max_length=50) group_id, group = ForeignKey(UserGroup, backref='user', comment='分组') # 一对多 # 一行实现多对多关系,无需自己写中间表 tags = ManyToMany(Tags, table_name='article', comment='标签', to_table='tags') ``` #### 3.2 定义数据库字段方法 如你所见,我们不再需要写Column,我们重新定义了字段的写法 如:username = String(comment="用户名称", max_length=50) ##### 通用参数说明 | 字段 | 类型 | 说明 | |-------------|-------|--------------------------------------------------------------| | comment | str | 数据库注释,也是admin引用的注释字段 | | nullable | bool | 字段是否可空,默认是False。True:不可为null(True就是加上 not null),注意,多对多没有这个参数 | | primary_key | bool | 是否主键,默认false | | doc | str | python文档的注释(与数据库无关) | | default | any | 默认值,值得注意的是,它并不是数据库的默认值,如果可空值改为不可空,migrate的时候可能会报错 | | kwargs | any | 其他Column可用的参数 | ##### int类型方法 Integer(comment=None, nullable=False, primary_key=False, doc=None, default=None, **kwargs) # 通常我们只需要关注以下这几个参数即可 number = Integer('数量', nullable=False, default=1) ##### varchar类型方法 String(comment=None, nullable=False, max_length=255, primary_key=False, doc=None, default=None, **kwargs) # 参数说明(这里只展示有区别的参数,其他参数请查看通用参数) :param max_length: 字符长度,默认255 # 常用配置 nickname = String("名称", nullable=True, max_length=30, default="匿名用户") ##### bool类型方法 Boolean(comment=None, nullable=False, primary_key=False, doc=None, default=None, **kwargs) # 常用配置 activity = Boolean("名称", nullable=True, default=False) ##### DateTime类型方法 DateTime(comment=None, nullable=False, auto_now=False, auto=False, primary_key=False, doc=None, default=None, **kwargs): # 参数说明(这里只展示有区别的参数,其他参数请查看通用参数) :param auto_now: True: 创建时是否自动填充现在的时间,只在创建时更新。 :param auto: True: 是否自动更新时间,创建时和每次更新时都会自动更新 ##### Date类型方法 Date(comment=None, nullable=False, auto_now=False, auto=False, primary_key=False, doc=None, default=None, **kwargs): # 参数说明(这里只展示有区别的参数,其他参数请查看通用参数) :param auto_now: True: 创建时是否自动填充现在的时间,只在创建时更新。 :param auto: True: 是否自动更新时间,创建时和每次更新时都会自动更新 ##### Time类型方法 Date(comment=None, nullable=False, auto_now=False, auto=False, primary_key=False, doc=None, default=None, **kwargs): # 参数说明(这里只展示有区别的参数,其他参数请查看通用参数) :param auto_now: True: 创建时是否自动填充现在的时间,只在创建时更新。 :param auto: True: 是否自动更新时间,创建时和每次更新时都会自动更新 ##### 外键关系(一对多) ForeignKey(to: Union[db.Model, str], backref: str, comment: str = None, to_table: str = None, nullable: bool = False, doc: str = None, default=None, **kwargs): # 参数说明(这里只展示有区别的参数,其他参数请查看通用参数) :param to: 关联的表,可以是其他模型,也可以是其他模型的名称(字符串类型) :param backref: 外键关系引用 :param to_table: 外键表名称,如果to为str类型的话,这个参数必填 返回一个元组(两个参数),第一个参数是关联表的key,第二个参数是关系字段relationship。 示例:user_id, user = ForeignKey(...) 详细实例在下面 ##### 外键关系(多对多) ManyToMany(to: Union[db.Model, str], table_name: str, comment: str = None, to_table=None, secondary=None, backref: str = None, doc: str = None, **kwargs): # 参数说明(这里只展示有区别的参数,其他参数请查看通用参数) :param to: 关联的表,可以是其他模型,也可以是其他模型的名称(字符串类型) :param table_name: 当前表的名称(即__tablename__) :param to_table: 外键表名称,如果to为str类型的话,这个参数必填 :param backref: 外键关系引用,如果不设置,默认为[类名]_set,如:User类中定义了ForeignKey字段,则backref=user_set 详细实例在下面 _更多方法正在加入中..._ #### 3.3、CModel类(自定义的Model,增加新功能) 继承CModel类,你将默认拥有以下属性,后面不再声明 | 字段 | 类型 | 说明 | |-------------|-----------|----------------------------------------| | id | int | 主键自增,每个表都有id,无需再手动添加id(类似Django的用法) | | create_time | datetime | 创建时间,创建时自动获取时间 | | update_time | datetime | 修改时间,修改时自动更新时间 | | delete_time | datetime | 删除时间,删除时自动获取、可以用做过滤是否被软删除。not None即已删除 | ##### 一个示例: models.py ```python from cc_flask.models import String, Boolean, CModel, ForeignKey, ManyToMany class UserGroup(CModel): name = String('分组名', default=True) class User(CModel): username = String(comment="用户名称", max_length=50) # 一对多,返回一个元组,第一个参数是外键id,第二个参数是代码中引用的关系(即relationship()方法) group_id, group = ForeignKey(UserGroup, backref='user_set', comment='分组') # 关联的表也可以使用字符串类型,但必须要传入to_table参数 # group_id, group = ForeignKey('UserGroup', backref='user_set', comment='分组', to_table='user_group') # 多对多,关联的表可以使用字符串类型,但必须要传入to_table参数 tags = ManyToMany('Tags', 'user', '标签', to_table='tags') class Tags(CModel): # 同样的,User表外键关联了Tags表,Tags表可以反向查User,反向字段为user_set(即User表名 + _set) # 如:print(Tags.query.get(1).user_set) # 输出:[, ] name = String("标签", max_length=20) ``` views.py 文件 ```python from app.models import User, UserGroup, Tags def index(): # 一对多演示 print(User.query.get(1).group) # 输出 # 反向引用 print(UserGroup.query.get(1).user_set) # 输出 [, ] # 多对多演示 print(User.query.get(1).tags) # 输出 [, ] # 反向引用 print(Tags.query.get(1).user_set) # 输出 [, ] ``` #### 3.4、models字段解析器 类似于序列化器,获取query得到的数据解析出来,得到最终需要返回的数据。 如:print(user.get_default()) 输出:[{"id": 1, "is_activity": True, "username": "风语"}, {"id": 2, "is_activity": False, "username": "小明"}...] >default: 常用于列表等,读取少量字段或比较长用的字段的接口 >detail: 常用于详情等,需要读取大量字段的接口 ##### 示例: models.py ```python from cc_flask.models import db class User(db.Model): # 省略其他字段... # 定义解析器字段 default = ['id', ("group", 'detail'), 'is_activity', 'username'] # 如果default中的字段和detail重复,你也可以这么用 detail = [*default, ('create_time', '%Y-%m-%d')] ``` view.py ```python from app.models import User def index(): user = User.query.flast() print(user.get_default()) # 获取default中的字段 # 输出:[{"id": 1, "group": {...group中的detail}, "is_activity": True, "username": "风语"}] print(user.get_detail()) # 获取detail中的字段 # 输出:[{"id": 1, "group": {...group中的detail}, "is_activity": True, "username": "风语", "create_time": "2023-05-17 10:30:43"}] ``` ##### 使用说明 解析器字段列表中可以传入两种类型 1)、字符串类型,传入models字段名,自动处理字段 default = ['id', 'username'...] 2)、元组类型,参数1为models字段名,参数2为解析的操作 # 元组:('字段名', '解析方式/转换类型/日期格式') default = ['id', ("group", 'detail'), ("create_time", '%Y-%m-%d %H:%M:%S')...] # 元组参数说明: # 参数1:字段名 # 参数2:根据参数1的字段类型,可以有不同的解析方式,规则如下 元组参数可填充的值: 1、外键(ForeignKey、ManyToMany): 示例:('group', 'detail') 可选值(str类型):'detail'、'default' 'detail':解析外键字段时,使用detail的规则解析(外键表未定义detail/default时,返回{}) 'default':解析外键字段时,使用default的规则解析(外键表未定义detail/default时,返回{}) 2、基础类型(String、Int、Float、Bool):指定转换类型,如果转换失败(即不符合转换规则),将原样返回。 示例:('id', str) 可选值(对象类型):int、float、bool、str等基础类型 int:指定转换int类型 float:指定转换float类型 bool:指定转换bool类型 str: 指定转换str类型 3、日期时间(DateTime、Data、Time):格式化输出字符串 示例:('create_time', '%Y-%m-%d %H:%M:%S') 默认格式为"%Y-%m-%d %H:%M:%S" > 📢注意事项:在多对一,多对多关系中,可能会出现N+1查询,需要再查询过程中设置查询方式 一个示例: ``` # 我有一个User表,通过group字段多对多关联到Group表,当我需要获取每个用户的所有分组的时候,可以这么做 # 通过options设置joinedload,避免出现N+1查询 user = User.query.options(models.db.joinedload(User.group)).all() # 在user的detail中设置 detail = [..., ('gropu', 'default')],即可联动获取所有gropu data = [i.detail() for i in user] ``` ##### 自定义models字段解析器: 你可以通过get_field()方法添加自定义解析器。 示例: models.py ```python from cc_flask.models import db class User(db.Model): # 省略其他字段... # 定义解析器列表 my_list = ['id', ("group", 'detail'), 'is_activity', 'username'] ``` view.py ```python from app.models import User def index(): user = User.query.flast() # 用法1,通过传入my_list 实现自己自定义字段解析 user.get_field(User.my_list) # 用法2,直接传入一个list,特殊接口更灵活,用法类似 user.get_field(['id', ("group", 'detail'), 'username']) ``` #### 3.5、逻辑删除(软删除) 如果你继承CModel,将默认自带软删除功能,无论是filter、filter_by、再或者get、all 这些方法都将自动过滤软删除的结果。 简单用法: ```python from app.models import User def index(): user = User.query.filter_by(id=1) # 直接调用delete()方法删除即可实现软删除。 user.delete() # 恢复软删除项 user.restore() # 物理删除,即直接从数据库中删除,无法恢复 user.hard_delete() # 2.使用:默认filter、filter_by、get、all等方法都会自动过滤软删除后的结果。也就是每个查询都会加入 delete_time IS NULL 条件 User.query.filter(User.username == '张三').all() User.query.filter_by(username='张三').all() User.query.all() # 返回所有数据(不包括已删除的) User.query.get(1) # 如果主键为已删除的数据id,则返回None。 ``` > 📢注意:使用join或者outerjoin时,连接表不会自动过滤删除项,需要手动加入过滤条件 ##### 方法说明 # 删除: delete() # 重写了delete()方法,如需物理删除请使用hard_delete() restore() # 恢复删除的数据,仅可恢复逻辑删除后的数据 hard_delete() # 物理删除,真正从数据库中删除,删除后不可恢复 # 取数据 filter_all() # 类似filter()方法,但该方法不过滤软删除数据 get_all() # 类似get() 方法,但该方法不过滤软删除数据 with_deleted() # 当前查询不再过滤软删除,如:query.with_deleted().filter() ,后面的filter、get等方法不再过滤软删除数据 ##### 注意:必须使用cc_flask.models.db,或者继承cc_flask.models.CModel才有这些方法。admin不会排除掉逻辑删除的数据 ### 四、请求响应参数处理器(RRManage) 请求响应管理器可以根据传入的参数,将请求参数转换为RRManage类的属性,似的接收参数更简单。 同时可以校验参数必填,设置默认值等功能 #### 4.1 RRManage类说明 ###### 最简单的用法 ```python from cc_flask.request_handle import RRManage # 如,请求接口为:http:xxx.com/get_userinfo?name=张三&age=18&sex=男 # 那么你可以这么接收 def get_userinfo(): # 接收参数,直接传递str给RRManage,RRManage自动收集请求参数 r = RRManage('name', 'age', 'sex') # 使用 print(r.name, r.age, r.sex) ``` ###### 必填项校验 ``` # 在参数后边跟着两个下划线(__)即可设置必填,参数的值用于返回错误的提示 RRManage('name__', sex__="性别", age__='年龄') # 设置必填后,如果前端没有传入对应的字段。将会返回如下报错信息 { "data": [ { "describe": "用户名", "field": "username", "field_des": "username(用户名)" }, { "describe": "邮箱", "field": "email", "field_des": "email(邮箱)" } ], "err_cmsg": "必填参数:用户名、邮箱", "err_code": 400, "err_msg": "缺少必填参数:username(用户名)、email(邮箱)", "page": null } ``` ###### 高级用法(设置默认值、类型转换) 1. 设置默认值、属性类型,如果未获取到数据,将返回默认值 ``` # RRManage的值可以接收一个元组,元组参数:(描述, 默认值, 转换的类型) # 第一个为描述,第二个为默认值,第三个为需要转换的类型 r = RRManage(name="姓名", age=("年龄", 0, int), sex=("性别", "未知")) print(r.sex) # 假设此时请求中没有sex属性或为null,输出结果:未知 print(type(r.age)) # 输出结果: ``` 2. 使用RV类 ``` # RV类型与元组类似,同样接受3个参数,描述、默认值、转换类型,用法如下 from cc_flask.request_handle import RV r = RRManage(name="姓名", age=RV("年龄", data_type=int), sex=RV(describe="性别", default="未知")) # 如你所见,RV可以让你的代码更具可读性,也更灵活,根据个人喜好选用 # 后期更新会加入更多功能,都会基于RV ``` > 📢注意:默认值会在获取不到前端传参或者值为null的时候生效,效果如下 #### 4.2 required_args装饰器 required_args装饰器其实就是调用RRManage类,用法跟RRManage一致,只是接收参数的方式不太一样。 ###### 一个例子 ```python from cc_flask.request_handle import required_args, RV @required_args(name="姓名", age=("年龄", 0, int), sex=RV("性别", "未知")) def index(r): # r是一个RRManage对象 print(type(r)) # 输出 ``` #### 4.3 RRManage的响应方法 ###### 成功响应方法 ```python from cc_flask.request_handle import required_args @required_args(name="姓名", age=("年龄", 0, int), sex=("性别", "未知")) def index(r): """ 返回参数说明: data: 返回的参数 page:分页数据 err_msg: 错误描述 kwargs: 还可以在后面追加其他字段填充,可填充到返回的字典中。方便某些接口补充字段 return: 格式:如: {"data": null, "err_cmsg": null, "err_code":0 , "err_msg":"ok", "page":null} """ return r.response_success(data=None, page=None, err_msg='ok') ``` ###### 返回失败响应 ```python from cc_flask.request_handle import required_args @required_args(name="姓名", age=("年龄", 0, int), sex=("性别", "未知")) def index(r): """ 返回参数说明: data: 返回的参数 page:分页数据 err_msg: 错误描述 kwargs: 还可以在后面追加其他字段填充,可填充到返回的字典中。方便某些接口补充字段 return: 格式:如: {"data": null, "err_cmsg": null, "err_code":-1, "err_msg":"错误描述,给程序员看的", err_cmsg="错误描述,给用户看的", "page":null} """ return r.response_error(code=-1, err_msg='错误描述,给程序员看的', err_cmsg="错误描述,给用户看的", data=None) ``` ###### 成功响应(结果分页) ```python from cc_flask.request_handle import required_args from app.models import User @required_args(name="姓名", age=("年龄", 0, int), sex=("性别", "未知")) def index(r): """ 注意:response_paginate使用的是models里面的default配置的值作为返回,所以必须先配置default 返回参数说明: _query: 需要分页的query err_msg: 错误描述 err_cmsg:错误描述,展示给用户看的描述 kwargs: 其他字段填充,可填充到返回的字典中。方便某些接口补充字段 return: 格式:如: {"data": null, "err_cmsg": null, "err_code":-1, "err_msg":"错误描述,给程序员看的", err_cmsg="错误描述,给用户看的", "page":null} """ query = User.query.filterd(is_activity=True) return r.response_paginate(_query=query, err_msg='ok', err_cmsg=None) ``` ### 五、数据库迁移 _注意:migrate对sqlite的支持很不友好,如果修改字段,很有可能出问题,因为sqlite不支持alter修改_ # 1、初始化(如果有migrations文件夹,跳过此步骤) # 📢注意:开始新项目时,请先将模板中的migration文件夹删除,再进行初始化。 flask db init # 2、迁移数据库,-m后面是迁移描述 flask db migrate -m 'UpdateInfo' # 3、同步数据库(升级数据库) flask db upgrade # 其他常用命令: flask db history # 显示迁移列表 flask db current # 显示数据库的迁移列表 flask db merge # 合并迁移文件(多人操作是会出现冲突,合并即可) flask db downgrade # 降级数据库(回退到上一个版本,或任意版本) # 其他注意事项: # 1、执行migrate后,必须执行upgrade同步数据库,才能进行下一次的migrate # 2、如需新增app(应用),需要在flaskr.migrate文件中import相应的models ### 五、错误码设计 标准化错误码可以更快速准确的定位错误 参考http状态码设计 #### 3.1. 参数约定 | 字段 | 类型 | 是否可空 | 说明 | |----------|--------|-------|---------------------------------| | data | dict | 可空 | 数据 | | page | dict | 可空 | 分页数据 | | err_code | int | 不可空 | 返回的状态码 | | err_msg | string | 可空 | 状态说明 | | err_cmsg | string | 可空 | 状态说明(给用户看的说明,如果没有,则可以提示err_msg) | #### 3.2. 状态码说明 ###### 错误码分类 | 分段 | 分段描述 | |-----|-------------------------------------------| | 0 | 成功处理 | | -1 | 未知错误 | | 4XX | 【客户端错误】请求包含语法错、参数错误、路径错误、输入错误等无法完成请求的情况 | | 5XX | 【服务端错误】在服务器处理请求期间出现的错误 | | 6XX | 【数据库错误】数据库层级的错误,如操作数据库时的报错 | ###### 客户端错误分类(常用) | 分段 | 分段描述 | |------|-----------------------------------------| | 40X | 请求传参错误,如:路径错误、缺少参数、请求方式错误、未登录(缺少参数的一种)等 | | 42X | 权限错误,如:权限不足、不满足条件、等错误 | | 45X+ | 预留客户端其他错误(大于450,小于500的状态码,开发期间可自定义设置) | ###### 自定义唯一错误 自定义唯一错误,是一个6位错误码,前3位与错误码分类保持一致,后3位表示唯一值 >示例: >403001,自定义表述为未登录(无token), >403002,自定义表述为登录过期(token失效) #### 3.3. 预设错误码 | 错误码 | 易触发对象 | 错误信息 | |-----|---------|-------------------------------------------| | 0 | - | 请求成功 | | -1 | 所有 | 未知错误 | | 400 | 开发者 | 缺少必填参数、参数类型错误、参数值错误 | | 401 | 用户 | 参数错误,用户输入错误等用户行为产生的错误,如:表单输入格式错误等 | | 403 | 用户 | 未登录、登录过期 | | 404 | 用户、开发者 | 找到不对象,请求中找不到对象,如一篇文章被删除后用户仍然请求获取,将触发404错误 | | 405 | 开发 | 请求方式错误,如:使用POST请求,但接口不支持等 | | 420 | 用户 | 权限不足、没有权限操作 | | 421 | 用户 | 条件不满, | | 500 | 开发 | 服务器层级的错误,如后端代码错误等 | | 502 | 开发 | 服务不可用 | | 600 | 开发 | 数据错误、读取数据库错误等 | ## 参与贡献 1. 由mjinnn独立设计开发 ## 特技 暂无内容 ## 历史版本 #### 1.1 Beat(2023.12.1 更新): 1.为避免cc_flask.models中的Model 与sqlalchemy的Model容易混淆, 该版本将cc_flask.models中的Model改名为 CModel 2.优化说明文档 3.优化软删除方法,filter、filter_by、get、all等方法,默认自带软删除 4.增加with_deleted方法,调用该方法可以获取已经被软删除的数据 5.重写get_or_404、first_or_404方法,返回json而不是一个html 6.RRManage增加to_dict(获取定义的传参)、req_args(获取前端传如并且已定义的参数)属性,可快速获取前端传参 7.优化RRManage代码 8.其他优化 #### 1.0 Beta(2023.6.6 合并主分支): 1. 加入sqlalchemy,使用数据库更简单 1.1 加入Integer()、String()、Boolean()等方法定义基础数据类型、更简洁直接(有点类似Django的用法) 1.2 加入ForeignKey()、ManyToMany()方法,定义一对多、多对多类型。 1.3 加入Model基础类、Model继承了sqlalchemy的Model,Model默认加入id、create_time等字段、表名默认使用类名等功能 1.4 加入软删除功能(通过Model.query.delete()进行软删除,.filter()方法已经过滤好软删除项) 2. 加入migrate迁移工具,更简单高效安全,每一次修改都有迹可循,迁移、撤回更简单,不用手动修改数据库 3. 加入admin工具、开发期间操作数据更简单,不再需要手动修改数据库。 3.1 加入自动获取所有数据表单,也就是说只要在models中定义了一个Model类,就会在admin中出现 3.2 加入基础配置,打开就是直观好用。 4. 加入RRManage(请求响应处理器),简单的方式接受请求参数,验证必填参数。处理返回结果等功能 5. 加入全局异常捕获,处理全局异常,debug模式下打印报错日志,调试更方便