结合项目的Flask学习与分享

背景与简介


背景


  • 基于公司内部的训练营活动,开发了一款基于微信运动数据及好友关系,进行运动竞赛的名为WeRunPlus的结合安卓与WebApp的小应用。

简介


  • Flask 是一个 Python 实现的 Web 开发微框架。“微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。
  • 我们的项目恰好需要Flask的“微”这一点,但又不仅仅满足于这一点,所以,利用Flask的灵活性对其进行了扩展。

Flask与项目


一个最小的应用——从0到1


  • 安装配置等相关内容可网上搜索,这里不再熬述。一个最小的 Flask 应用,即单个文件,便可非常方便地完成一个服务。

    hello.py

  from flask import Flask
  app = Flask(__name__)

  @app.route('/')
  def hello_world():
      return 'Hello World!'

  if __name__ == '__main__':
      app.run()
  • 运行python hello.py,服务就启动了。
结合项目的Flask学习与分享_第1张图片
15-39-20.jpg
  • 然后,在浏览器中访问http://ip:5001/
    便可看到“Hello World!”的字样。这其中发生的过程如下。

    • 首先,导入了 Flask 类。这个类的实例将会是 WSGI 应用程序。
    • 接下来,创建一个该类的实例,第一个参数是应用模块或者包的名称。 如果你使用单一的模块(如本例),你应该使用 name ,因为模块的名称将会因其作为单独应用启动还是作为模块导入而有不同( 也即是 'main' 或实际的导入名)。这是必须的,这样 Flask 才知道到哪去找模板、静态文件等等。详情见 Flask 的文档。
    • 然后,使用 route() 装饰器告诉 Flask 什么样的URL 能触发函数。
    • 这个函数的名字也在生成 URL 时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息。
    • 最后用 run() 函数来让应用运行在本地服务器上。 其中 if name == 'main': 确保服务器只会在该脚本被 Python 解释器直接执行的时候才会运行,而不是作为模块导入的时候。

我们的扩展——从1到10


结合项目的Flask学习与分享_第2张图片
15-40-22.jpg
  • 结合目前流行的框架,从单文件到到项目的扩展如上图所示。
  • 首先werunplus是项目文件夹,run.py为项目的启动文件。启动文件除了负责服务启动外,主要是便于大家进行全局常量的自定义配置而设置的。比如图中的flask.log日志文件,便是在run.py中设置的。再比如,更换不同的端口进行访问,,方便大家进行测试。
  • app文件夹是项目的主干。
    • _init_.py是Flask核心类实例化的地方,同时也能进行其他初始化设置。
    • database.py用来进行数据库的基本配置。
    • views为路由层。负责将请求与后台逻辑进行对应。
    • dao为数据访问对象层。除了要和数据库打交道外,返回的数据还需要进行处理,才能进行json化,所以这里不仅包含数据库逻辑,也包含数据格式化部分。
    • model为数据模型层。将数据库与对象对应起来,形成model,方便dao层操作。
      • 这里使用的orm来自SQLAlchemy。SQLAlchemy执行效率高,可定制程度高,他有很好的SQL转义功能,即将目前逻辑转成sql,然后可根据需求,增加相应SQL,便能结合model进行处理,该扩展倍受国外友人喜爱,但也因复杂的需求,需手写部分sql,且中文文档近乎为0,所以,这也给我们的学习带来了麻烦。
    • templates为模板层,主要放html模板文件。
      • 因为,要做的展示部分是WebApp,有很多页面要做,同时也有数据要拿,所以,最一开始自己做了调研和测试。Flask自带jinja这种通过python实现的页面渲染工具,但考虑到项目开发的快捷性,我们在前端还使用了前端渲染工具handlebars对页面进行带数据的渲染。如下图所示,在具有较高渲染速度的情况下,handlebars既能独立于html之外,亦能有很多方便的函数供前端人员使用。
      • 结合两者,使用jinja做后端模板渲染,handlebars实现前端的带数据的页面渲染,既能保证模板复用和信息安全,也能保证数据的异步交互。(西安旅游后台部分可以借鉴。)
    • common为基础工具层。这里主要放些大家常用的公共方法,比如,python数据的json转换等。
    • static为静态层,这里包括js、css、图片等静态内容,方便进行加载。
结合项目的Flask学习与分享_第3张图片
22-35-09.jpg

请求流程图


结合项目的Flask学习与分享_第4张图片
17-22-18.jpg

框架执行流程图


结合项目的Flask学习与分享_第5张图片
17-22-23.jpg

项目的问题和启示


小项目的多人开发


15-42-36.jpg

Flask=服务器软件+python框架,这里省去了服务器相关软件的部署,方便了大家的开发工作。如上图,在面对多人开发的情况下,我们有一个唯一的项目目录用来面向用户,而与此同时也保证每个人都拥有一个自己的服务器端口方便修改调试。另外一点是,一开始项目设计耦合度就比较低,方便了大家代码的融合。当然项目大了的话,还是要通过使用git等版本库进行版本控制,避免风险。

python严格的数据格式及编码要求


事实上,python对数据格式及编码要求很严格,一般从数据库中取出的数据都要进行类型转换,才能正常转为json,这里提供一种常用的方法,方便对多类型的数据进行格式化。当然,这个函数只是解决了部分情况,还有很多需要大家进行补充。

def json_serial(obj):
    """JSON serializer for objects not serializable by default json code"""
    if isinstance(obj, datetime):
        serial = obj.strftime("%Y-%m-%d %H:%M:%S")
        return serial
    if isinstance(obj, date):
        serial = str(obj)
        return serial
    if isinstance(obj, decimal.Decimal):
        return float(obj)
    raise ValueError (str(type(obj) ) )

def retInJson(data="",msg="操作成功!",ret=0):
    res = {
        "ret":ret,
        "msg":msg,
        "data":data,
    }
    data = json.dumps(res,default=json_serial)
    return data

你可能感兴趣的:(结合项目的Flask学习与分享)