因起初开始自己入门web的时候,是由以前我们的大牛主管来引导,非常感谢他一直以来的指导。接下来的系列文章主要是自己再这几天使用了flask之后,尝试继续使用Bottle封装成类似的那种来处理。
关于代码说明
每一章节对应当前主题的代码来提供。
框架说明
- Token令牌:使用JWT令牌机制,可用于单页面应用程序,合适做前后端分离等应用
- bottle全局异常处理
- 使用wtforms表单验证相关的表单提交参数
- 重写HTTPError 统一异常返回格式,方便前端开发
- 更详细log日志记录,记录整个请求链路相关记录,也可以记录自己定义记录
- peewee orm数据库的使用和简单封装
- 类似Flask蓝图应用
详细日志记录示例如下:
2019-12-27 16:56:04:121 | process_id:40532 process_name:MainProcess | thread_id:24044 thread_name:MainThread | INFO |
{
"headers":"{ "Content-Length": "0", "Content-Type": "text/plain", "Aaa": "sadasd", "Sfdsdui": "sdasd", "User-Agent": "PostmanRuntime/7.21.0", "Accept": "*/*", "Cache-Control": "no-cache", "Postman-Token": "75287742-d0c9-429a-bdc5-f03072480e8d", "Host": "127.0.0.1:8889", "Accept-Encoding": "gzip, deflate", "Connection": "keep-alive" }",
"host":"127.0.0.1:8889",
"ip":"127.0.0.1",
"url":"[http://127.0.0.1:8889/?sdasd=43543&username=22222222222&AAAAAAAAAAAA=%E8%AF%B4%E7%9A%84%E5%B0%B1%E6%98%AF%E7%9A%84%E5%AF%8C%E5%AE%B6%E5%A4%A7%E5%AE%A4](http://127.0.0.1:8889/?sdasd=43543&username=22222222222&AAAAAAAAAAAA=%E8%AF%B4%E7%9A%84%E5%B0%B1%E6%98%AF%E7%9A%84%E5%AF%8C%E5%AE%B6%E5%A4%A7%E5%AE%A4)",
"method":"POST",
"params":{
"query_string":"sdasd=43543&username=22222222222&AAAAAAAAAAAA=说的就是的富家大室",
"query":{
"sdasd":"43543",
"username":"22222222222",
"AAAAAAAAAAAA":"说的就是的富家大室"
},
"forms":""
},
"req_stime":"2019-12-27 16:56:03.773712",
"req_links_logs":[
{
"link_index":1,
"event_des":"请求开始"
},
{
"link_index":2,
"event_des":"第三方接口请求日志",
"msg_dict":{
"url":"[https://www.baidu.com](https://www.baidu.com/)",
"method":"GET",
"params":null,
"params_str":"None",
"this_time_out":"15s",
"req_stime":"2019-12-27 16:56:03",
"cost_time":58.509,
"state_code":"200",
"result":"<!DOCTYPE html> <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>'); </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html> "
},
"remarks":"第三方接口请求【OK】"
},
{
"link_index":3,
"event_des":"第三方接口请求日志",
"msg_dict":{
"url":"[https://juejin.im/post/5dee431c518825122e0a764c](https://juejin.im/post/5dee431c518825122e0a764c)",
"method":"POST",
"params":{
"ssdsd":230
},
"params_str":"{'ssdsd': 230}",
"this_time_out":"15s",
"req_stime":"2019-12-27 16:56:04",
"cost_time":179.218,
"state_code":"404",
"result":"<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>Cannot POST /post/5dee431c518825122e0a764c</pre> </body> </html> "
},
"remarks":"第三方接口请求【FAIL】,status_code:404 错误"
},
{
"link_index":4,
"event_des":"第三方接口请求日志",
"msg_dict":{
"url":"[https://www.jianshu.com/p/c192f3dc3e0c](https://www.jianshu.com/p/c192f3dc3e0c)",
"method":"POST",
"params":{
"ssdsd":230
},
"params_str":"{'ssdsd': 230}",
"this_time_out":"15s",
"req_stime":"2019-12-27 16:56:04",
"cost_time":96.011,
"state_code":"403",
"result":"<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html> <head><title>403 Forbidden</title></head> <body bgcolor="white"> <h1>403 Forbidden</h1> <p>You don't have permission to access the URL on this server. Sorry for the inconvenience.<br/> Please report this message and include the following information to us.<br/> Thank you very much!</p> <table> <tr> <td>URL:</td> <td>https://www.jianshu.com/p/c192f3dc3e0c</td> </tr> <tr> <td>Server:</td> <td>zurich</td> </tr> <tr> <td>Date:</td> <td>2019/12/27 16:56:04</td> </tr> </table> <hr/>Powered by Tengine</body> </html> "
},
"remarks":"第三方接口请求【FAIL】,status_code:403 错误"
},
{
"link_index":5,
"event_des":"请求结束"
}
],
"rsp_data":{
"msg":"roleId 必须传入",
"code":400,
"error_code":10031
},
"cost_time":"353.0"
}
长远目标计划
基于Bottle做一个简单后台权限管理系统,自用
系统是基于https://github.com/wuyouzhuguli/FEBS-Vue的前端源码上来做,后端就改成了我自己用bottle
1.登入界面
2.系统主页
3.数据分析页
本文目标
- 框架模块分层
准备环节
关于环境安装等问题,在此也不再重复的叙述,其实网上也有大把的教程。
项目规划
因为后续我们的很多的项目都依赖一个公共的基础库,而且相关的开发都是基于自由的基础库上进行开发,所以我个人的洗好,则是把相关的一些基础的放在同一个大项目文件夹下,这样也方便后续的其他微服务开发。
1. 基础库划分
因为我个人的喜欢,还是喜欢把一些独立的东西放在独立的包下去管理。可能划分多也未必是好事,不过目前我基础库也不算是非常多,所有相关的包都是独立的。
相关的包的解析如下:
- lib 一些其他第三库源码包
- xcache 关于redis缓存工具包
- xcors 关于bottle跨域的处理包
- xexception 关于bottley全局异常捕获插件包
- xtyform 关于bottle表单验证处理包
- xwtforms 关于bottle使用WTForms表单验证处理包
- xhelper 关于常用一些工具类的封装
- xhttp 关于reuqests简单的封装,加上日志记录
- xlog 日志记录初始化基础吧包
- xmodels 关于peewee基础modeljw包
- xplugins 其他插件包的封装
- xresponse 关于响应报文统一封装包统一返回格式,方便前端开发
- xscheduler 任务调度基础
- xsingnal 信号库的简单封装,封装发送信号和接受信号的装饰器
2. API相关开发
因为每个项目都是独立的,所以后续各自项目开发人员都负责自己的项目即可。相关基础库原则上,只需要新增相关其他方法,后续同步上不及时的问题,也不会因为某个人修改了基础库,导致某个项目异常等问题。
相关的包的解析如下:
- api 项目设计接口开发路由
- apirsp 统一定义返回响应体
- config 项目设计常量等信息配置(一般线上的话可能 会写入环境变量中)
- jobs 定义相关定时任务或消息队列任务
- log app产品的日志记录
- models 数据库下对于的ORM模型
- utils 针对此应用下一些特定的工具类
- validators 封装当前API接口使用到的表单校验器
- x-tests API单元测试
-- app 应用示例对象
-test-results.xml 测试结果
- test_start 加载x-tests下的测试用例,执行测试脚本
总结
因为个人喜欢问题,可能相关分包其实是有问题,过多的分包后期也许可能对管理来说可能会有点不好,不过,我个人喜欢的事一个独立的包处理独立的事,所以分包上,可能有点个人形式主义。