五分钟菜鸟学会Python玩转SQL的神器!

五分钟菜鸟学会Python玩转SQL的神器!

背景

其实一开始用的是pymysql,但是发现维护比较麻烦,还存在代码注入的风险,所以就干脆直接用ORM框架。

ORM即Object Relational Mapper,可以简单理解为数据库表和Python类之间的映射,通过操作Python类,可以间接操作数据库。

Python的ORM框架比较出名的是SQLAlchemy和Peewee,这里不做比较,只是单纯讲解个人对SQLAlchemy的一些使用,希望能给各位朋友带来帮助。

sqlalchemy版本: 1.3.15pymysql版本: 0.9.3mysql版本: 5.7

初始化工作

一般使用ORM框架,都会有一些初始化工作,比如数据库连接,定义基础映射等。

以MySQL为例,创建数据库连接只需要传入DSN字符串即可。其中echo表示是否输出对应的sql语句,对调试比较有帮助。

from sqlalchemy import create_engineengine = create_engine('mysql+pymysql://$user:$password@$host:$port/$db?charset=utf8mb4', echo=True)

登录后复制

个人设计

对于我个人而言,引进ORM框架时,我的项目会参考MVC模式做以下设计。其中model存储的是一些数据库模型,即数据库表映射的Python类;model_op存储的是每个模型对应的操作,即增删查改;调用方(如main.py)执行数据库操作时,只需要调用model_op层,并不用关心model层,从而实现解耦。

├── main.py├── model│ ├── __init__.py│ ├── base_model.py│ ├── ddl.sql│ └── py_orm_model.py└── model_op ├── __init__.py └── py_orm_model_op.py

登录后复制

映射声明(Model介绍)

举个栗子,如果我们有这样一张测试表

create table py_orm ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '唯一id', `name` varchar(255) NOT NULL DEFAULT '' COMMENT '名称', `attr` JSON NOT NULL COMMENT '属性', `ct` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `ut` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON update CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY(`id`))ENGINE=InnoDB COMMENT '测试表';

登录后复制

在ORM框架中,映射的结果就是下文这个Python类

# py_orm_model.pyfrom .base_model import Basefrom sqlalchemy import Column, Integer, String, TIMESTAMP, text, JSONclass PyOrmModel(Base): __tablename__ = 'py_orm' id = Column(Integer, autoincrement=True, primary_key=True, comment='唯一id') name = Column(String(255), nullable=False, default='', comment='名称') attr = Column(JSON, nullable=False, comment='属性') ct = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP'), comment='创建时间') ut = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'), comment='更新时间')

登录后复制

首先,我们可以看到PyOrmModel继承了Base类,该类是sqlalchemy提供的一个基类,会对我们声明的Python类做一些检查,我将其放在base_model中。

# base_model.py# 一般base_model做的都是一些初始化的工作from sqlalchemy import create_enginefrom sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()engine = create_engine("mysql+pymysql://root:123456@127.0.0.1:33306/orm_test?charset=utf8mb4", echo=False)

登录后复制

其次,每个Python类都必须包含__tablename__属性,不然无法找到对应的表。

第三,关于数据表的创建有两种方式,第一种当然是手动在MySQL中创建,只要你的Python类定义没有问题,就可以正常操作;第二种是通过orm框架创建,比如下面:

# main.py# 注意这里的导入路径,Base创建表时会寻找继承它的子类,如果路径不对,则无法创建成功from sqlachlemy_lab import Base, engineif __name__ == '__main__': Base.metadata.create_all(engine)

登录后复制

创建效果:

...2020-04-04 10:12:53,974 INFO sqlalchemy.engine.base.EngineCREATE TABLE py_orm (id INTEGER NOT NULL AUTO_INCREMENT,name VARCHAR(255) NOT NULL DEFAULT '' COMMENT '名称',attr JSON NOT NULL COMMENT '属性',ct TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,ut TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id))

登录后复制

第四,关于字段属性

1.primary_key和autoincrement比较好理解,就是MySQL的主键和递增属性。2.如果是int类型,不需要指定长度,而如果是varchar类型,则必须指定。3.nullable对应的就是MySQL中的NULL 和 NOT NULL4.关于default和server_default: default代表的是ORM框架层面的默认值,即插入的时候如果该字段未赋值,则会使用我们定义的默认值;server_default代表的是数据库层面的默认值,即DDL语句中的default关键字。

Session介绍

在SQLAlchemy的文档中提到,数据库的增删查改是通过session来执行的。

>>> from sqlalchemy.orm import sessionmaker>>> Session = sessionmaker(bind=engine)>>> session = Session()>>> orm = PyOrmModel(id=1, name='test', attr={})>>> session.add(orm)>>> session.commit()>>> session.close()

登录后复制

如上,我们可以看到,对于每一次操作,我们都需要对session进行获取,提交和释放。这样未免过于冗余和麻烦,所以我们一般会进行一层封装。

1.采用上下文管理器的方式,处理session的异常回滚和关闭,这部分与所参考的文章是几乎一致的。

# base_model.pyfrom contextlib import contextmanagerfrom sqlalchemy.orm import sessionmaker, scoped_sessiondef _get_session(): """获取session""" return scoped_session(sessionmaker(bind=engine, expire_on_commit=False))()# 在这里对session进行统一管理,包括获取,提交,回滚和关闭@contextmanagerdef db_session(commit=True): session = _get_session() try: yield session if commit: session.commit() except Exception as e: session.rollback() raise e finally: if session: session.close()

登录后复制

2.在PyOrmModel中增加两个方法,用于model和dict之间的转换

class PyOrmModel(Base): ... @staticmethod def fields(): return ['id', 'name', 'attr'] @staticmethod def to_json(model): fields = PyOrmModel.fields() json_data = {} for field in fields: json_data[field] = model.__getattribute__(field) return json_data @staticmethod def from_json(data: dict): fields = PyOrmModel.fields() model = PyOrmModel() for field in fields: if field in data: model.__setattr__(field, data[field]) return model

登录后复制

3.数据库操作的封装,与参考的文章不同,我是直接调用了session,从而使调用方不需要关注model层,减少耦合。

# py_orm_model_op.pyfrom sqlachlemy_lab.model import db_sessionfrom sqlachlemy_lab.model import PyOrmModelclass PyOrmModelOp: def __init__(self): pass @staticmethod def save_data(data: dict): with db_session() as session: model = PyOrmModel.from_json(data) session.add(model) # 查询操作,不需要commit @staticmethod def query_data(pid: int): data_list = [] with db_session(commit=False) as session: data = session.query(PyOrmModel).filter(PyOrmModel.id == pid) for d in data: data_list.append(PyOrmModel.to_json(d)) return data_list

登录后复制

4.调用方

# main.pyfrom sqlachlemy_lab.model_op import PyOrmModelOpif __name__ == '__main__': PyOrmModelOp.save_data({'id': 1, 'name': 'test', 'attr': {}})

登录后复制

完整代码请参见:

​​https://github.com/yangancode/python_lab/tree/master/sqlachlemy_lab​​

以上就是五分钟菜鸟学会Python玩转SQL的神器!的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2241886.html

(0)
上一篇 2025年2月26日 20:45:56
下一篇 2025年2月24日 14:26:18

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 时间序列特征提取的Python和Pandas代码示例

    使用Pandas和Python从时间序列数据中提取有意义的特征,包括移动平均,自相关和傅里叶变换。 前言 时间序列分析是理解和预测各个行业(如金融、经济、医疗保健等)趋势的强大工具。特征提取是这一过程中的关键步骤,它涉及将原始数据转换为有意…

    2025年2月26日 编程技术
    200
  • 小白必读!十大被低估的Python自带库!

    大 大家在学习python的过程中,都会了解到python的一个强大的功能在于各种强大的第三方库函数,大家只需要通过pip install 即可安装我们需要的库函数。 家往往只是关注自己安装的python库,却忽略了python自带的库函数…

    2025年2月26日 编程技术
    200
  • 用于清理数据的五个简单有效 Python 脚本

    将 PDF 转换为 CSV 在机器学习中,我们应该少一些“数据清理”,多一些“数据准备”。当我们需要从白皮书、电子书或其他PDF文档中抓取数据时,这个脚本为我节省了很多时间。 import tabula#获取文件pdf_filename =…

    2025年2月26日
    200
  • Python爬取天气数据及可视化分析

    正文  大家好,我是Python人工智能技术 天气预报我们每天都会关注,我们可以根据未来的天气增减衣物、安排出行,每天的气温、风速风向、相对湿度、空气质量等成为关注的焦点。得到温湿度度变化曲线、空气质量图、风向雷达图等结果,为获得未来天气信…

    2025年2月26日 编程技术
    200
  • Python 批量加水印只需一行命令!

    工作的时候,尤其是自媒体工作者,必备水印添加工具以保护知识产权图片,网上有许多的在线/下载的水印添加工具,但他们或多或少都存在以下问题: 1. 在线工具需要将图片上传到对方服务器,信息不安全。 2. 很多工具不具备批量处理功能。 3. 很多…

    2025年2月26日 编程技术
    200
  • 一行 Python 代码实现并行

    Python 在程序并行化方面多少有些声名狼藉。撇开技术上的问题,例如线程的实现和 GIL,我觉得错误的教学指导才是主要问题。常见的经典 Python 多线程、多进程教程多显得偏”重”。而且往往隔靴搔痒,没有深入探讨…

    2025年2月26日
    200
  • Python 字符串总结,建议收藏!

    什么是 Python 字符串 字符串是包含一系列字符的对象。字符是长度为 1 的字符串。在 Python 中,单个字符也是字符串。但是比较有意思的是,Python 编程语言中是没有字符数据类型的,不过在 C、Kotlin 和 Java 等其…

    2025年2月26日
    200
  • Python使用Dash开发网页应用

    Python Dash开发Web应用的控件基础 本文主要是通过Dash的Checklist组件,简单介绍使用Dash开发的Web应用 展示效果如下: python dash简单基础 Dash应用程序由两部分组成: 第一部分是应用程序的布局(…

    2025年2月26日
    200
  • Python自动化办公之Excel拆分并自动发邮件

    需求 需要向大约 500 名用户发送带有 Excel 附件的电子邮件,同时必须按用户从主 Excel 文件中拆分数据以创建他们自己的特定文件,然后将该文件通过电子邮件发送给正确的用户 需求解析 大致的流程就是上图,先拆分 Excel 数据,…

    2025年2月26日 编程技术
    200
  • 提高数据科学效率的八个Python神库!

    1、Optuna Optuna 是一个开源的超参数优化框架,它可以自动为机器学习模型找到最佳超参数。 最基本的(也可能是众所周知的)替代方案是 sklearn 的 GridSearchCV,它将尝试多种超参数组合并根据交叉验证选择最佳组合。…

    2025年2月26日
    200

发表回复

登录后才能评论