ORM操作mysql/mariadb

本文详细介绍了Python的ORM库SQLAlchemy,包括其重要特性、安装、使用方法,特别是如何创建ORM模型,新增和查询数据。通过示例代码展示了如何连接数据库、声明模型、同步表、操作数据库以及执行复杂的查询操作,如条件查询、函数使用、多表连接、分组去重、排序分页等。
摘要由CSDN通过智能技术生成

一、ORM简介

1.1、理解ORM

  • ORM(Object Relational Mapping),对象关系映射
  • 编程语言中的“虚拟对象数据库”
  • 像操作Python对象一样操作数据库

1.2、ORM的重要特性

  • 面向对象的编程思想,方便扩充
  • 少写(几乎不写)SQL,提升开发效率
  • 支持多种类型的数据库,方便切换
  • ORM技术成熟,能解决绝大部分问题

1.3、ORM模型框架的选择

在这里插入图片描述

SQLAlchemy:Pypi官方网站帮助文档


二、SQLAlchemy ORM模型介绍

  • 数据库支持情况:PostgreSQL、MySQL、MariaDB、SQLite、Oracle、SQL Server
  • Python兼容情况:cPython2.7、cPython3.6+、PyPy:2.1+
  • 企业级的ORM框架
  • 支持SQL中的几乎所有功能
  • 分层架构:SQL构造系统、DBAPI交互层
  • 支持连接池

2.1、SQLAlchemy安装

安装:pip install SQLAlchemy

验证

>>> import sqlalchemy
>>> sqlalchemy.__version__
'1.4.21'
>>>

2.2、SQLAlchemy的使用

  • 第一步,开始连接数据库
  • 第二步,声明ORM模型基类
  • 第三步,实现ORM模型类
  • 第四步,同步数据库表
2.2.1、第一步,开始连接数据库
  • 延迟连接(Lazy Connecting):只有在真正操作数据库的时候才连接数据库

  • 连接代码示例

    from sqlalchemy import create_engine
    
    create_engine(
    	'mysql://root:123456@127.0.0.1:3306/school?charset=utf8',
    	echo=True,
    	future=True
    )
    

连接参数解释

  • url(默认第一个参数)
    连接到哪种类型的数据库,如:mysql
    以哪种数据库连接器(驱动)来连接数据库,默认使用官方的连接器,如:mysqlclient
    数据库连接参数:用户名、密码、数据库服务地址,端口等
  • echo:是否输出logging日志信息,显示执行的sql语句
  • future:使用SQLAlchemy 2.0 API风格

SQLAlchemy配置

  • MySQL数据库URL参数格式:mysql://user:password@host:port/db_name?charset=uft8mb4

当password中含有特殊字符时,需要进行转义

>>>from urllib.parse import quote_plus
>>>quote_plus('kx%jj5/g')
>>>'kx%25jj5%2Fg'

连接器的选择

如果加上charset报错,可以去掉,各个版本可能不一样。

  • 使用mysqlclient:mysql+mysqldb://user:password@host:port/db_name?charset=uft8mb4
  • 使用pymysql:mysql+pymysql://user:password@host:port/db_name?charset=uft8mb4
  • 使用mysql-connector-python:mysql+mysqlconnector://user:password@host:port/db_name?charset=uft8mb4
  • MariaDB模式:mariadb+pymysql://user:password@host:port/db_name?charset=uft8mb4
  • 其它:aiomysql、cymysql、oursql
2.2.2、第二步,声明ORM模型基类

示例代码

from sqlalchemy.orm import declarative_base

Base = declarative_base()
2.2.3、第三步,实现ORM模型类

示例代码

from sqlalchemy import Column, Integer, String, DateTime

class Student(Base):
	"""学生信息表"""
	__tablename__ = 'student'
	
	id = Column(Integer, primary_key=True)
	stu_no = Column(Integer, nullable=False, comment='学号')
	stu_name = Column(String(16), nullable=False, comment='姓名')
	created_at = Column(DateTime, comment='创建日期')
2.2.4、 第四步,同步数据库表
  • 手动创建数据库
  • 创建表:Base.metadata.create_all()
  • 删除表:Base.metadata.drop_all()

2.3、Column常用参数

  1. name:数据库表中对应的列的名称,默认是变量名称
  2. type_:该列对应的数据类型
  3. primary_key:是否为主键
  4. autoincrement:是否为自动增加,默认是“auto”,主键自动增加
  5. comment:数据库表中字段的注释,同步到数据库表中
  6. doc:注释,不会同步到数据库表中
  7. nullable:是否为空,默认是True
  8. default:指定默认值
  9. unique:唯一性约束,默认是False
    10.index:是否是索引,默认是False

2.4、ORM模型字段类型

在这里插入图片描述在这里插入图片描述


三、新建ORM模型

3.1、用户的地址信息表

用户表数据字典
在这里插入图片描述
地址表数据字典
在这里插入图片描述

3.2、CHAR类型的数据如何表示

  • 导入:优选范围广的类型,支持多种数据库,其次再选择对应数据库的类型

    from sqlalchemy.types import CHAR
    from sqlalchemy.dialects.mysql import TINYINT, CHAR
    
  • 使用

    phone_no = Column(CHAR(11), comment='电话号码')
    age = Column(TINYINT(unsigned=True), comment='年龄')
    

3.3、SQLAlchemy中的关联关系

  • 一对多关系,外键关联,如:一个用户有多个地址列表
  • 一对一关联,如:一个用户基础信息对应唯一的详细信息
  • 多对多关联,使用场景不多

一对多关联关系

示例代码

class UserAddress(Base):
	"""地址信息表"""
	# 建立外键
	user_id = Column(Integer, ForeignKey(User.id))
	# 建立关联关系,backref:反向引用,User模型引用的addresses属性,可以访问address表中与用于关联的所有地址信息
	user = relationship('User', backref='addresses')

一对一关联关系

示例代码

class User(Base):
	"""用户信息表"""
	profile = relationship('UserProfile', backref='user', uselist=False)

3.4、相关代码

包路径代码
在这里插入图片描述

数据库连接相关

from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base

SQLALCHEMY_DATABASE_URL = 'mariadb+pymysql://root:123456@127.0.0.1:3306/learn_data_base'

# 准备连接
engine = create_engine(
    SQLALCHEMY_DATABASE_URL,
    echo=True,
    future=True
)

# 声明ORM模型的基类
Base = declarative_base()


def create_table():
    """同步数据库表"""
    Base.metadata.create_all(bind=engine)


def drop_table():
    """删除所有数据库表"""
    Base.metadata.drop_all(bind=engine)

用户地址表

from datetime import datetime

from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey
from sqlalchemy.types import CHAR
from sqlalchemy.orm import relationship

from learn_orm.db_engine import Base
from learn_orm.models.user import User


class UserAddress(Base):
    """用户地址信息表"""
    __tablename__ = 'account_user_address'
    id = Column(Integer, primary_key=True)
    area = Column(String(256), nullable=False, comment='地址')
    phone = Column(CHAR(11), comment='电话号码')
    remark = Column(String(512), comment='备注')
    is_valid = Column(Boolean, default=True, comment='是否有效')
    create_at = Column(DateTime, default=datetime.now(), comment='创建时间')

    # 外键关联
    user_id = Column(Integer, ForeignKey(User.id), comment='关联的用户ID')
    # 建立一对多联系:关联的模型'User',backref:User模型反向关联的属性,lazy:对关联的属性值进行筛选
    user = relationship('User', backref='addresses')

    def __repr__(self):
        return f'{self.area}_{self.phone_no}'

用户信息表

from datetime import datetime
from enum import IntEnum

from sqlalchemy import Column, String, Integer, Enum, Boolean, DateTime, ForeignKey
from sqlalchemy.dialects.mysql import TINYINT
from sqlalchemy.orm import relationship, backref

from learn_orm.db_engine import Base


class SexEnum(IntEnum):
    """
    性别枚举,IntEnum: 整形枚举比较节省内存
    """
    MAN = 1  # 男
    WOMAN = 2  # 女


class User(Base):
    """用户信息表"""
    __tablename__ = 'account_user'

    id = Column(Integer, primary_key=True)
    username = Column(String(32), nullable=False, unique=True, comment='用户名')
    password = Column(String(512), nullable=False, comment='密码')
    real_name = Column(String(16), comment='真实姓名')
    sex = Column(Enum(SexEnum), default=None, comment='性别')
    age = Column(TINYINT(unsigned=True), default=0, comment='年龄')
    is_valid = Column(Boolean, default=True, comment='是否有效')
    created_at = Column(DateTime, default=datetime.now(), comment='创建时间')

    # 用户详情:建立一对一的关联关系
    profile = relationship('UserProfile', backref='user', uselist=False)

    def __repr__(self):
        return f'{self.username}_{self.sex}'


class UserProfile(Base):
    """用户详细信息表"""
    __tablename__ = 'account_user_profile'
    id = Column(Integer, primary_key=True)
    hobby = Column(String(255), comment='爱好')

    # 外键
    user_id = Column(Integer, ForeignKey(User.id), comment='关联的用户ID')
    # 用户详情:建立一对一的关联关系
    user = relationship('User', backref=backref('profile', uselist=False))
    # profile = relationship('User', backref='profile', uselist=False)

启动

from learn_orm.models.user import User
from learn_orm.models.address import UserAddress
from learn_orm.db_engine import create_table, drop_table

if __name__ == '__main__':
    # create_table()
    drop_table()

四、ORM新增数据

操作步骤

  1. 第一步,构造ORM模型对象
  2. 第二步,添加到session
  3. 第三步,提交到数据库
  4. 第四步,出现异常,回滚事务

4.1、第一步,构造ORM模型对象

参考代码

user = User(
	username='wangli',
	password='123456',
	real_name='王莉',
	age=12
)

4.2、第二步,添加到session

  • 添加一个对象:session.add(user)
  • 添加多个对象:session.add_all([user1, user2, user3])

关于Session

  • 建立与数据库之间的会话
  • 使用Session对数据库中的数据进行增删改查
  • 使用Session进行事务控制(提交与回滚)
  • 使用完后需要关闭它:session.close()

Session的创建

  • 方式一:实例化Session类

    from sqlalchemy.orm import Session
    
    with Session(engine) as session:
    	session.add(User())
    	session.commit()
    
  • 方式二:使用工厂函数创建

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(engine)

# begin():开启事务执行,上下文自动提交
with Session.begin() as session:
	session.add(User())

4.3、第三步,提交到数据库

示例代码

with Session(engine) as session:
	session.add(user_obj) # 提交一条数据
	session.add_all([user1,user2,user3]) # 提交多条数据
	session
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值