Flask到吐血

Python(Flask)模块化编程开发

2019-09-29  本文已影响0人  西北望高楼
为什么要模块化编程开发?

Python,最伟大的地方就在于Python拥有各种强大的库。所以,使用Python进行开发工作,最重要的也是要学会使用Python库,不去重复造轮子,那么在Python-Web开发中,也要学会将功能模块化,这样做不仅可以降耦,还会在团队开发或者多项目开发中,做到敏捷开发,而且在项目升级中,更容易做到维护/重构。所以,在开发中,做到模块化开发,是很有必要的。

那么,根据我自己的经验谈一谈,我在Flask开发Web应用/Api服务的时候怎么做到模块化开发。

下面是一个Flask应用的层级关系,后面的讲解,将会根据这个层级来说明怎么进行模块化编程开发。

.
├── ERROR_CODE.MD
├── README.md
├── app                       App应用
│   ├── __init__.py 
│   ├── api                  API模块
│   ├── config               配置模块
│   ├── handler              逻辑处理模块
│   ├── libs                 内部库
│   ├── models
│   ├── static
│   ├── templates
│   ├── utils                工具类模块
│   └── view                 视图模块
├── env                       Python库
├── logs
├── requirements.txt
└── run.py                    运行脚本

这是一个简单的完整的Flask项目层级关系,模块化的主要核心在于api、handler、view这三个部分。

通常的,我们把对外提供API服务的处理放在api模块里面,把业务逻辑处理部分放在handler里面,把提供页面展示与页面处理的逻辑放在view里面。

1. API模块: api

主要处理对外提供API接口的代码。

在这里面,我们尽量不做对数据逻辑的处理,只处理业务逻辑,比如我们有一个创建员工邮箱的接口:

@user_mail_bp.route('/user', methods=['POST'])
def user_mail_create():
    """创建邮箱"""
    mail = get_json('mail', u'邮箱', valid=[Required()])
    name = get_json('name', u'名称', valid=[Required()])

    info = {}.update(mail=mail, name=name)
    # 1. 请求企业邮箱接口创建邮箱
    res, data = user_exmail.create_with_user_info(user=info)
    if res is not True:
        msg = data
        return error(msg=msg)

    # 2. 将创建的邮箱存放到数据库
    res, data = user_handler.create_with_user_info(user=info)
    if res is not True:
        msg = data
        return error(msg=msg)

    return success(msg=u'请求成功', data=data)

这个接口示例中,我们主要有两个部分的处理,第一个是解析参数与返回结果,第二个是生成邮箱并保存到数据库。可以看到,我们并没有把步骤1中怎么调用企业邮箱接口创建邮箱的逻辑和步骤2中怎么保存到数据库的逻辑放在这里,而是调用函数去处理的,我们只去分析操作结果。

那么,这样做的好处是什么呢?

低耦合性。是的,我们不去关心该怎么去创建邮箱,只关心业务的部分:为谁创建邮箱,创建结果如何。这样,即使创建邮箱的方式变化了,只需要在创建邮箱的函数里去处理,或者直接更改调用的函数就可以了,极大的减少了工作量。

在上面的代码中,我们使用user_exmail.create_with_user_info(user=info)去创建邮箱,那么,这个函数又是什么呢?这就需要说说handler模块了。

2. handler模块

数据请求、数据操作等逻辑处理代码主要封装在这里。

比如上面谈到的user_exmail.create_with_user_info(user=info)函数:

def create_with_user_info(user_info):
    """
    新建用户企业邮箱
    :param user_info: dict,包含为用户信息
    :return: 创建结果 True,group / False,msg
    """
    mail = user_info.get('mail', None)
    name = user_info.get('name', None)

    if not mail:
        msg = u'mail不允许为空'
        return False, msg
    if not name:
        msg = u'name不允许为空'
        return False, msg

    # 请求接口创建群组
    try:
        res = exmail_store.create_user(
            mail=mail,
            name=name
        )
    except Exception as e:
        msg = u'企业邮箱接口异常:{}, 请联系管理员'.format(e.message)
        return False, msg

    # 解析创建群组返回值
    if not res:
        msg = u'企业邮箱接口异常, 返回值为空, 请联系管理员'
        return False, msg
    res_data = json.loads(res.text)
    err_code = res_data.get('errcode', None)
    if err_code != 0:
        msg = res_data.get('errmsg', None)
        return False, msg
    return True, group

这里把创建企业邮箱的请求单独封装起来,放在handler中,这个逻辑一旦完成,即函数编写完成,只需要在外部调用就够了。如果函数不满足使用,比如创建邮箱方式变化了,或者API升级了,那么我们只需要重新编写一个函数就可以,这样既保留原有函数功能,也保证升级后的函数功能,对调用方来说可以做到兼容。

同样的,如果有新的项目,有相同的功能需求,我们只需要把该函数移植过去就可以了,这是模块化的编程的另一种好处:可移植性。

3. view视图模块

该部分和API模块部分类似,只是处理的是返回页面的路由,这里不多做解释,给大家一个test模块的示例:

@test_view.route('/t/test')
def home():
    mail = get_json('mail', u'邮箱', default='')
    if not mail:
        return render_template('test/error.html')
    # 创建邮箱部分
    ······
    return render_template('test/success.html')

Python模块化编程开发还有一个重要的好处:团队合作,敏捷开发。由于是模块化,多人开发的时候,只需要分工不同的模块,每个人负责的模块只需要提供函数,别人调用就行,先提供函数模拟返回参数,后进行逻辑开发,这样在互不干涉的工作中,快速完成自己负责的部分,进而完成整个项目开发任务。

上一篇下一篇

猜你喜欢

热点阅读