当前位置:首页 > 文章列表 > 数据库 > MySQL > 用python写通用restful api service(二)

用python写通用restful api service(二)

来源:SegmentFault 2023-01-10 14:09:00 0浏览 收藏

有志者,事竟成!如果你在学习数据库,那么本文《用python写通用restful api service(二)》,就很适合你!文章讲解的知识点主要包括MySQL、python、flask、rest-api,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~

今天项目已经能够做一个简单的后端服务了,在mysql中新建一个表,就能自动提供restful api的CURD服务了。

关键点

  • 根据REST的四种动词形式,动态调用相应的CURD方法;
  • 编写REST与基础数据库访问类之间的中间层(baseDao),实现从REST到数据访问接口之间能用业务逻辑处理;
  • 编写基础数据库访问类(dehelper),实现从字典形式的参数向SQL语句的转换;

实现的rest-api

实现了如下形式的rest-api

[GET]/rs/users/{id}
[GET]/rs/users/key1/value1/key2/value2/.../keyn/valuen         
[POST]/rs/users     
[PUT]/rs/users/{id}
[DELETE]/rs/users/{id}

基础数据库访问类

该类实现与pymysql库的对接,提供标准CURD接口。

准备数据库表

在数据库对应建立users表,脚本如下:

CREATE TABLE `users` (
  `_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) CHARACTER SET utf8mb4 DEFAULT '' COMMENT '标题名称',
  `phone` varchar(1024) DEFAULT '',
  `address` varchar(1024) DEFAULT NULL,
  `status` tinyint(4) DEFAULT '1' COMMENT '状态:0-禁;1-有效;9删除',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`_id`),
  UNIQUE KEY `uuid` (`_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='表';

新建数据库配置文件(configs.json)

数据连接配置,不入版本库。

{
  "db_config": {
    "db_host": "ip",
    "db_port": 1234,
    "db_username": "root",
    "db_password": "******",
    "db_database": "name",
    "db_charset": "utf8mb4"
  }
}

对接pymysql接口

用函数exec_sql封装pymysql,提供统一访问mysql的接口。is_query函数用来区分是查询(R)还是执行(CUD)操作。出错处理折腾了好久,插入异常返回的错误形式与其它的竟然不一样!返回参数是一个三元组(执行是否成功,查询结果或错误对象,查询结果数或受影响的行数)

with open("./configs.json", 'r', encoding='utf-8') as json_file:
    dbconf = json.load(json_file)['db_config']


def exec_sql(sql, values, is_query=False):
    try:
        flag = False       #是否有异常
        error = {}         #若异常,保存错误信息
        conn = pymysql.connect(host=dbconf['db_host'], port=dbconf['db_port'], user=dbconf['db_username'],
                               passwd=dbconf['db_password'], db=dbconf['db_database'], charset=dbconf['db_charset'])
        with conn.cursor(pymysql.cursors.DictCursor) as cursor:
            num = cursor.execute(sql, values)       #查询结果集数量或执行影响行数
        if is_query:                                #查询取所有结果
            result = cursor.fetchall()
        else:                                       #执行提交
            conn.commit()
        print('Sql: ', sql, ' Values: ', values)
    except Exception as err:
        flag = True
        error = err
        print('Error: ', err)
    finally:
        conn.close()
        if flag:
            return False, error, num if 'num' in dir() else 0
    return True, result if 'result' in dir() else '', num

查询接口

pymysql的查询接口,可以接受数组,元组和字典,本查询接口使用数组形式来调用。现在此接口只支持与条件组合参数。

def select(tablename, params={}, fields=[]):
    sql = "select %s from %s " % ('*' if len(fields) == 0 else ','.join(fields), tablename)
    ks = params.keys()
    where = ""
    ps = []
    pvs = []
    if len(ks) > 0:                    #存在查询条件时,以与方式组合
        for al in ks:
            ps.append(al + " =%s ")
            pvs.append(params[al])
        where += ' where ' + ' and '.join(ps)

    rs = exec_sql(sql+where, pvs, True)
    print('Result: ', rs)
    if rs[0]:
        return {"code": 200, "rows": rs[1], "total": rs[2]}
    else:
        return {"code": rs[1].args[0], "error": rs[1].args[1], "total": rs[2]}

插入接口

以数组形式提供参数,错误信息解析与其它接口不同。

def insert(tablename, params={}):
    sql = "insert into %s " % tablename
    ks = params.keys()
    sql += "(`" + "`,`".join(ks) + "`)"               #字段组合
    vs = list(params.values())                        #值组合,由元组转换为数组
    sql += " values (%s)" % ','.join(['%s']*len(vs))  #配置相应的占位符
    rs = exec_sql(sql, vs)
    if rs[0]:
        return {"code": 200, "info": "create success.", "total": rs[2]}
    else:
        return {"code": 204, "error": rs[1].args[0], "total": rs[2]}

修改接口

以字典形式提供参数,占位符的形式为:%(keyname)s,只支持按主键进行修改。

def update(tablename, params={}):
    sql = "update %s set " % tablename
    ks = params.keys()
    for al in ks:                                    #字段与占位符拼接
        sql += "`" + al + "` = %(" + al + ")s,"
    sql = sql[:-1]                                   #去掉最后一个逗号
    sql += " where _id = %(_id)s "                   #只支持按主键进行修改
    rs = exec_sql(sql, params)                       #提供字典参数
    if rs[0]:
        return {"code": 200, "info": "update success.", "total": rs[2]}
    else:
        return {"code": rs[1].args[0], "error": rs[1].args[1], "total": rs[2]}

删除接口

以字典形式提供参数,占位符的形式为:%(keyname)s,只支持按主键进行删除。

def delete(tablename, params={}):
    sql = "delete from %s " % tablename
    sql += " where _id = %(_id)s "
    rs = exec_sql(sql, params)
    if rs[0]:
        return {"code": 200, "info": "delete success.", "total": rs[2]}
    else:
        return {"code": rs[1].args[0], "error": rs[1].args[1], "total": rs[2]}

中间层(baseDao)

提供默认的操作数据库接口,实现基础的业务逻辑,单表的CURD有它就足够了。有复杂业务逻辑时,继承它,进行扩展就可以了。

import dbhelper


class BaseDao(object):

    def __init__(self, table):
        self.table = table

    def retrieve(self, params={}, fields=[], session={}):
        return dbhelper.select(self.table, params)

    def create(self, params={}, fields=[], session={}):
        if '_id' in params and len(params) 

动态调用CURD

根据客户调用的rest方式不同,动态调用baseDao的相应方法,这个很关键,实现了它才能自动分配方法调用,才能只需要建立一个数据表,就自动提供CURD基本访问功能。还好,动态语言能很方便的实现这种功能,感慨一下,node.js更方便且符合习惯^_^

    method = {
        "GET": "retrieve",
        "POST": "create",
        "PUT": "update",
        "DELETE": "delete"
    }
    
getattr(BaseDao(table), method[request.method])(params, [], {})

说明:

  • table是前一章中解析出来的数据表名,这块就是users;
  • method应该是定义一个常量对象,对应rest的动词,因为对ypthon不熟,定义了一个变量先用着,查了下常量说明,看着好复杂;
  • request.method 客户请求的实际rest动词;
  • params是前一章中解析出来的参数对象;

完整代码

git clone https://github.com/zhoutk/pyrest
cd pyrest
export FLASK_APP=index.py
flask run

小结

至此,我们已经实现了基本的框架功能,以后就是丰富它的羽翼。比如:session、文件上传、跨域、路由改进(支持无缝切换操作数据库的基类与子类)、参数验证、基础查询功能增强(分页、排序、模糊匹配等)。
感慨一下,好怀念在node.js中json对象的写法,不用在key外加引号。

补丁

刚把基础数据库访问类中的insert方法的参数形式改成了字典,结果异常信息也正常了,文章不再改动,有兴趣者请自行查阅源代码。

今天关于《用python写通用restful api service(二)》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

版本声明
本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
Ubuntu的web服务器搭建系列之MySQL(JDK+Tomcat+MySQL+Nginx+Redis+NodeJS)Ubuntu的web服务器搭建系列之MySQL(JDK+Tomcat+MySQL+Nginx+Redis+NodeJS)
上一篇
Ubuntu的web服务器搭建系列之MySQL(JDK+Tomcat+MySQL+Nginx+Redis+NodeJS)
Centos7 上安装mysql遇上的问题:mysql无法正常启动
下一篇
Centos7 上安装mysql遇上的问题:mysql无法正常启动
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • SEO标题魔匠AI:高质量学术写作平台,毕业论文生成与优化专家
    魔匠AI
    SEO摘要魔匠AI专注于高质量AI学术写作,已稳定运行6年。提供无限改稿、选题优化、大纲生成、多语言支持、真实参考文献、数据图表生成、查重降重等全流程服务,确保论文质量与隐私安全。适用于专科、本科、硕士学生及研究者,满足多语言学术需求。
    20次使用
  • PPTFake答辩PPT生成器:一键生成高效专业的答辩PPT
    PPTFake答辩PPT生成器
    PPTFake答辩PPT生成器,专为答辩准备设计,极致高效生成PPT与自述稿。智能解析内容,提供多样模板,数据可视化,贴心配套服务,灵活自主编辑,降低制作门槛,适用于各类答辩场景。
    36次使用
  • SEO标题Lovart AI:全球首个设计领域AI智能体,实现全链路设计自动化
    Lovart
    SEO摘要探索Lovart AI,这款专注于设计领域的AI智能体,通过多模态模型集成和智能任务拆解,实现全链路设计自动化。无论是品牌全案设计、广告与视频制作,还是文创内容创作,Lovart AI都能满足您的需求,提升设计效率,降低成本。
    48次使用
  • 美图AI抠图:行业领先的智能图像处理技术,3秒出图,精准无误
    美图AI抠图
    美图AI抠图,依托CVPR 2024竞赛亚军技术,提供顶尖的图像处理解决方案。适用于证件照、商品、毛发等多场景,支持批量处理,3秒出图,零PS基础也能轻松操作,满足个人与商业需求。
    45次使用
  • SEO标题PetGPT:智能桌面宠物程序,结合AI对话的个性化陪伴工具
    PetGPT
    SEO摘要PetGPT 是一款基于 Python 和 PyQt 开发的智能桌面宠物程序,集成了 OpenAI 的 GPT 模型,提供上下文感知对话和主动聊天功能。用户可高度自定义宠物的外观和行为,支持插件热更新和二次开发。适用于需要陪伴和效率辅助的办公族、学生及 AI 技术爱好者。
    45次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码