【Python使用笔记】Flask进阶之路——Hello and Goodbye

其实网络上关于Flask的介绍文章数不胜数,所以本系列文并不是技术分享或者优化炫技,而是重个人学习的角度出发,简单谈谈自己是如何把玩Flask的。

      Hello Flask

        使用Flask这种PyWeb框架的人无非三种,要么是专业的;要么写算法、模块、脚本的忽然接到个前端展示的需求;要么是写了一路java忽然发现自己要和一个叫python的乖乖对接。我是后两种的结合(疯狂暗示不专业)。

        Flask有什么优点这里不做赘述,别问,问就是我是骄傲放纵的python!!!

        那么网上不少的Flask教程,他们的Hello World 大概都长成这个样子:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

app.run()

        其实你会发现,等你入门了,不只是Hello World ,他什么程序都长成这个样子:

        ① 创建 app 对象

        ② 配置路由以及对应的处理方法

        ③ run

        要什么Controller、Service、Mapper、POJO,我的MVC就是一页代码!

        至于页面,PyWeb的好基友Jinjia绝对首选,前后耦合的方式梦回暴力的 .jsp时代,页面代码大概长这样




    
    Title


    {{ words }}

       项目结构大概长这样

【Python使用笔记】Flask进阶之路——Hello and Goodbye_第1张图片

        但是这样的Web不是我们想要的,首先,他就算不上一个工程,你可以叫他“脚本”,但我更愿意叫他Demo,因为它会长大。想想他离一个成熟的Web还差什么?一个漂亮的项目结构、一个层次分明的架构、前后端分离的时尚方式。

        一个一个来,首先想想Spring的入口类长什么样,所以app.py就应该只有一行代码

app.run()

        之后的思路是:

        ① 利用Python的包机制,为我们的项目加一个 __init__.py来初始化我们入口py使用的app

        ② 单独的配置文件,在 __init__.py载入设置

        ③ 将路由和对应的处理方法单提出来作为Controller文件,在__init__.py装配给app

        这时他的项目结构是

【Python使用笔记】Flask进阶之路——Hello and Goodbye_第2张图片

        各个文件内容如下:

# app.py
from Normal import app
app.run()
# __init__.py
from flask import Flask
app = Flask(
    __name__,
    static_folder="./static",
    template_folder="./templates"
)
#加载配置文件内容
app.config.from_object('Normal.setting') 
# 加载 controller
from Normal.controller import index
# index.py
from Normal import app
@app.route('/')
def hello_world():
    return 'Hello World!'

        这回有点结构的样子,但还没有预想的好——路由就写在方法上面,能不能向VUE那样前端框架把路由和路由指向单独提出来,把一切弄得Restful一点,Flask自己提供了一个Restful的解决方案Flask-RESTful,附上地址 Flask-RESTful快速入门

       但是这里,我更推荐使用一个git上的一个开源组件flask_rest_controller,这个提供一个将路由提出来的更好方案,同时提供了一个更加明确、精准的接口定义方式,更加方便的Json数据解析方式。附上地址 Flask-REST-Controller 安装方式如下:

pip install flask-rest-controller
pip install --upgrade Flask

        他使用的是类似Flask-RESTful的方式,将路由与py文件里的class绑定,之后再class里定义这个路由的get、post、put等方法。与Flask-RESTful不同的:

        ① 每个class都继承于flask_rest_controller的Controller,并可以通过一个字典型字段 schema来定义这个class处理路由时的详细参数,样例如下:

schema = {
        'GET':{                     接受的请求类型
            'type':'string'         请求返回类型,可以是'object','array'
            :'properties':{         当type是object时,该object的字段信息
                'id':{              字段名
                    'type':'string' 字段类型'string','integer'
                },
                ...
            },
            :'items':{              当type是array时,该array的元素类型
                'type':'string'     元素类型
            },
        },
        ...
    }

             之后对应的写schema中配置的同名的方法,如def get()。其实“同名的方法”就是重写Controller的对应get、post等方法,所以schema不配置是有默认的,默认就是这个路由可由全部的访问类型访问。特别的,还可以重写 Controller的 prepare方法和after方法。prepare方法定义正式处理(执行get或post等)之前的操作,固定return True,不然......你懂before-upload怎么卡住得吧;after方法定义正式处理(执行get或post等)之后的操作。

        ② 使用一个元组List来定义路由映射,格式如下:

[
    (地址,对应的controller的py文件路径.类名,endpoint),
    ... ...
]

            之后在__init__.py,通过flask_rest_controller的set_routing,把这个List(ROUTING)给app:

from flask_rest_controller import set_routing
from route import ROUTING
set_routing(app, ROUTING)

        到这里我们已经拥有了一个相对漂亮的项目结构、一个相对层次分明的架构。对于前后端分离工作先给我们的app一点准备工作——跨域访问CORS,同样在__init__.py配置给app,有session需求的别忘了secret_key:

from flask_cors import CORS
app.secret_key = SECRET_KEY
CORS(app)

        下次再来试试把这个改造过的Flask Web项目和VUE整合一下

      Goodbye Jinjia

        最后,截止至目前我这个文章的代码样例如下

【Python使用笔记】Flask进阶之路——Hello and Goodbye_第3张图片

# start.py
__name__ = "RESTful"
from . import app
from .static.setting import HOST, PORT

app.run(host=HOST, port=PORT)
# __init__.py
from flask import Flask
from flask_rest_controller import set_routing
from flask_cors import CORS
from .route.route import get_routing
from .static.setting import SECRET_KEY,PROJECT_NAME
app = Flask(PROJECT_NAME)
app.config.from_object(PROJECT_NAME+'.static.setting')
app.secret_key = SECRET_KEY
CORS(app)
set_routing(app, get_routing())
# setting.py
# _*_ coding: utf-8 _*_
# ===================================================================================
# 服务器参数
# ===================================================================================
# 调试模式是否开启
DEBUG = True
# 项目名称,大小写敏感
PROJECT_NAME = 'RESTful'
# app密钥,使用 session必备
SECRET_KEY = 'NEULightBulb_ZhangJ'
# controller 的根地址 PROJECT_NAME.包名.
CONTROLLER_DIR = "RESTful.controller."
# 项目url context
CONTEXT_DIR = "/"
# 启动 HOST、PORT
HOST = 'XXX.XXX.XXX.XXX'
PORT = 8888
# route.py
from ..static.setting import CONTROLLER_DIR
from ..static.setting import CONTEXT_DIR
from ..route.route_list import ROUTING

def get_routing():
    rel = []
    for item in ROUTING :
        rel.append((CONTEXT_DIR+item[0],CONTROLLER_DIR+item[1],item[1][item[1].rindex('.')+1:]))
    return rel
# route_list.py
ROUTING = [
    ("heartbeat","basic.heartbeat"),
    ("api/submit","submit.submit"),
]

 

# basic.py
from flask_rest_controller import Controller

class heartbeat(Controller):
    schema = {
        'type': 'object',
        'properties':{
            'status':{
                'type':'string'
            }
        }
    }

    def get(self):
        return self.render_json({'status':'1'})
# submit.py
from flask_rest_controller import Controller

class submit(Controller):
    schema = {
        'post': {
            'type': 'object',
            'properties': {
                'result': {
                    'type': 'string',
                },
                'code': {
                    'type': 'integer',
                }
            },
        }
    }

    def prepare(self):
        self.storage['id_card'] = self.request.json.get('id_card')
        self.storage['phone'] = self.request.json.get('phone')
        self.storage['address'] = self.request.json.get('address')
        self.storage['select'] = self.request.json.get('select')
        return True

    def post(self):
        print(self.storage['id_card'],
              self.storage['phone'],
              self.storage['address'],
              self.storage['select'])
        return self.render_json({"status": 0})

 

你可能感兴趣的:(Python)