提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、装包
- 二、数据库直接生成模型类脚本文件(RefeshModels.bat)
- 二、我的模型类,也就是那个models.py
- 三、DbConfig.py
- 四、main.py(重点,示例代码在这里面)
前言
这段时间研究都在学习python,所以对Python SqlAlchemy对数据库各种操作整理(MySQL为例),大家相互学习,也当是作为笔记,以后copy来用。
一、装包
SqlAlchemy: pip install "sqlalchemyasyncio" aiomysql
db frist方式依赖包: pip install pymysql sqlacodegen
二、数据库直接生成模型类脚本文件(RefeshModels.bat)
bat
@echo off
chcp 65001 >nul
echo 正在强制刷新数据库模型(先删后建)...
if exist "models.py" del /f /q "models.py"
sqlacodegen mysql+pymysql://root:xxx@localhost/db_py_orm_test --outfile models.py
if %errorlevel% equ 0 (
echo 模型已强制覆盖更新!
) else (
echo 生成失败,请检查数据库连接或参数。
)
pause
1、这个脚本文件里面"models.py"这个就是模型类的文件路径了,我这里是根目录,你可以根据自己需要去改到其他目录;
2、数据库名字等连接字符串信息根据自己情况改一下就行
3、每次数据库更新了运行一下这个脚本就行
二、我的模型类,也就是那个models.py
python
from typing import Optional
import datetime
from sqlalchemy import DateTime, Float, String
from sqlalchemy.dialects.mysql import INTEGER
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
pass
class Author(Base):
__tablename__ = 'author'
Id: Mapped[str] = mapped_column(String(50), primary_key=True)
Name: Mapped[Optional[str]] = mapped_column(String(20))
Age: Mapped[Optional[int]] = mapped_column(INTEGER(11))
class Book(Base):
__tablename__ = 'book'
Id: Mapped[str] = mapped_column(String(50), primary_key=True, comment='ID')
CreateDatetime: Mapped[datetime.datetime] = mapped_column(DateTime, nullable=False, comment='CreateDate')
Title: Mapped[Optional[str]] = mapped_column(String(50), comment='Title')
Author_: Mapped[Optional[str]] = mapped_column('Author', String(20), comment='Author')
Price: Mapped[Optional[float]] = mapped_column(Float, comment='Price')
三、DbConfig.py
python
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
connectionString="mysql+aiomysql://root:xxx@localhost:3306/db_py_orm_test?charset=utf8"
asyncEngine = create_async_engine(
connectionString,
echo=False,
pool_size=10,
max_overflow=20
)
AsyncSessionLocal=async_sessionmaker(
bind=asyncEngine,
class_=AsyncSession,
expire_on_commit=False
)
async def getDatabase():
async with AsyncSessionLocal() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
finally:
await session.close()
四、main.py(重点,示例代码在这里面)
这里需要注意的是那个异步引擎一定要Dispose
python
import uuid
from sqlalchemy import text, select, update, delete, join, insert, exists
import asyncio
from sqlalchemy.sql.operators import and_, or_
from sqlalchemy.testing import in_
from DbConfig import AsyncSessionLocal, asyncEngine
from models import Book, Author
from datetime import datetime
"""
获取所有书籍信息 返回值是元组列表
"""
async def getBooks():
async with AsyncSessionLocal() as session:
return (await session.execute(text("SELECT * FROM book;"))).all()
"""
获取第一条:有就返回第一条,没有就是none,
返回的是元组|None
"""
async def getBookFirst():
async with AsyncSessionLocal() as session:
return (await session.execute(text("SELECT \
* \
FROM \
book \
WHERE \
Price > 200 \
ORDER BY \
CreateDatetime DESC;"))).first()
"""
返回一条或没有,
当存在多条结果抛出异常
"""
async def getBookByTitle(title):
async with AsyncSessionLocal() as session:
return (await session.execute(text("SELECT \
* \
FROM \
book \
WHERE \
Title = :title;"), {"title": title})).one_or_none()
"""
单一条件的筛选
"""
async def getBooksV2():
async with AsyncSessionLocal() as session:
return (await session.execute(select(Book).where(Book.Price > 50))).scalars().all()
"""
复杂条件筛选
"""
async def getBooksV3():
async with (AsyncSessionLocal() as session):
return (await session.execute(select(Book)
.where(
or_(
and_(Book.Price > 50, Book.Author.like("吴%")),
Book.Title == "红楼梦"
)
)
)).scalars().all()
"""
更新操作V1
"""
async def updatePrice():
async with AsyncSessionLocal() as session:
queryResult = await session.execute(update(Book)
.where(Book.Id == "981dcd3b-cbcc-4663-823b-87bebf76bfbe")
.values(Price=80))
await session.commit()
return queryResult.rowcount > 0
"""
更新操作V2
"""
async def updatePriceV2():
async with AsyncSessionLocal() as session:
book = (await session.execute(select(Book).where(Book.Id == "981dcd3b-cbcc-4663-823b-87bebf76bfbe"))) \
.scalars() \
.one_or_none()
if not book:
return "书籍信息不存在"
book.Price = 80
await session.commit()
return "OK"
"""
删除V1
"""
async def deleteBook():
async with AsyncSessionLocal() as session:
queryResult = await session.execute(delete(Book)
.where(Book.Id == "981dcd3b-cbcc-4663-823b-87bebf76bfbe"))
await session.commit()
return queryResult.rowcount > 0
"""
删除V2
"""
async def deleteBookV2():
async with AsyncSessionLocal() as session:
book = (await session.execute(select(Book)
.where(Book.Id == "ea1b2895-2210-4666-a4b5-fb68a8ff1c19"))) \
.scalars() \
.one_or_none()
if not book:
return "书籍信息不存在"
await session.delete(book)
await session.commit()
return "OK"
"""
联表查询
"""
async def getBooksV4():
async with AsyncSessionLocal() as session:
return (await session.execute(
select(join(Book, Author, Book.Author_ == Author.Name))
.where(Book.Price > 50)
)).all()
"""
联表查询(只要部分字段)
"""
async def getBooksV5():
async with AsyncSessionLocal() as session:
return (await session.execute(
select(Book.Title, Author.Name, Author.Age)
.select_from(join(Book, Author, Book.Author_ == Author.Name))
)).all()
"""
批量新增书籍
"""
async def batchInsertBooks(books):
async with AsyncSessionLocal() as session:
for book in books:
if not (await session.execute(select(exists().where(Author.Name == book["Author"])))).scalar():
return "作者信息不存在"
if (await session.execute(select(exists().where(Book.Title == book["Title"])))).scalar():
return "书籍信息已存在"
queryResult = await session.execute(insert(Book).values(books))
await session.commit()
if queryResult.rowcount > 0:
return "OK"
else:
return "新增失败"
"""
批量删除书籍
"""
async def batchDeleteBooks(ids):
async with AsyncSessionLocal() as session:
queryResult=await session.execute(delete(Book).where(Book.Id.in_(ids)))
await session.commit()
return queryResult.rowcount >0
async def main():
print("=====================================================================")
# books = await getBooks()
# for book in books:
# print(book)
# book=await getBookFirst()
# if book:
# print(book)
# else:
# print("Book not found")
# book=await getBookByTitle("西游记")
# if book :
# print(book)
# else:
# print("Book not found")
# books = await getBooksV3()
# for book in books:
# print(f"{book.Id} {book.Title} {book.Author} {book.Price} {book.CreateDatetime}")
# if await updatePrice():
# print("更新成功")
# else:
# print("更新失败")
# if (await updatePriceV2())!="OK":
# print("更新失败")
# else:
# print("更新成功")
# if await deleteBook():
# print("删除成功")
# else:
# print("删除失败")
# if (await deleteBookV2())!="OK":
# print("删除失败")
# else:
# print("删除成功")
# books = await getBooksV5()
# for book in books:
# print(book)
# result = await batchInsertBooks([
# {
# "Id": str(uuid.uuid4()),
# "Title": "红楼梦",
# "Author": "曹雪芹",
# "Price": 60,
# "CreateDatetime": datetime.now()
# }, {
# "Id": str(uuid.uuid4()),
# "Title": "西游记",
# "Author": "吴承恩",
# "Price": 80,
# "CreateDatetime": datetime.now()
# }])
# if result=="OK":
# print("新增成功")
# else:
# print(result)
if await batchDeleteBooks(["57e2cd30-537f-429b-bb35-d270264d48cd","7805a7af-5a96-4d33-b1a3-9ac9ef48d2a9"]):
print("删除成功")
else:
print("删除失败")
print("=====================================================================")
await asyncEngine.dispose()
print("OK")
if __name__ == "__main__":
asyncio.run(main())