一、Prisma库核心概述
1.1 用途与工作原理
Prisma是一款为Python开发者设计的现代ORM(对象关系映射)工具,核心作用是简化Python应用与关系型数据库的交互流程,支持PostgreSQL、MySQL、SQLite等主流数据库。其工作原理基于数据模型驱动:开发者通过定义简洁的Schema文件描述数据结构,Prisma引擎会自动将Schema转换为对应的数据库表结构,同时生成类型安全的Python客户端,让开发者无需编写复杂的SQL语句,直接通过面向对象的方式完成数据的增删改查操作。

1.2 优缺点分析
优点
- 类型安全:自动生成的客户端包含完整的类型提示,结合Python的类型检查工具(如mypy)可在编码阶段发现数据类型错误,大幅降低运行时异常概率。
- Schema即文档:Schema文件采用直观的语法,兼具数据结构定义与文档功能,团队协作时可直接通过Schema了解数据模型。
- 迁移管理便捷:内置的迁移工具支持数据库结构的版本控制,可轻松实现数据库表的创建、修改、删除,且能追踪迁移历史。
- 查询能力强大:支持链式查询、关联查询、批量操作等复杂场景,查询语法简洁易懂,比传统ORM更贴近自然语言。
缺点
- 生态成熟度待提升:相较于Django ORM、SQLAlchemy等老牌ORM,Python版Prisma的第三方插件和扩展较少。
- 学习曲线:对于习惯原生SQL或传统ORM的开发者,需要适应Prisma独特的Schema定义和查询风格。
- 性能损耗:在超高性能要求的场景下,ORM的封装会带来轻微的性能开销,极端场景下可能需要结合原生SQL优化。
1.3 License类型
Python Prisma库采用Apache License 2.0开源协议,该协议允许商业使用、修改和分发,只需保留原作者的版权声明,对开发者友好且无商业使用限制。
二、Prisma库安装与环境配置
2.1 安装前置条件
在安装Prisma之前,需确保本地环境满足以下要求:
- Python版本≥3.8(推荐3.9及以上)
- 已安装对应数据库的客户端工具(如PostgreSQL需安装psycopg2,MySQL需安装mysqlclient)
- 网络环境正常,可访问PyPI仓库
2.2 安装命令
Prisma的安装分为两个步骤:首先安装Python包,然后初始化Prisma引擎。
- 安装Python包
打开命令行终端,执行以下pip命令安装Prisma:bash pip install prisma - 初始化Prisma引擎 安装完成后,需要初始化Prisma的二进制引擎,执行以下命令:
bash prisma init执行该命令后,会在当前目录生成两个关键文件:schema.prisma:用于定义数据模型和数据库连接配置的核心文件。.env:用于存储数据库连接字符串等环境变量。
2.3 数据库连接配置
以SQLite数据库为例(无需额外安装服务,适合快速开发),修改schema.prisma文件中的datasource块:
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-py"
}
然后修改.env文件,设置数据库连接URL:
DATABASE_URL="file:./dev.db"
若使用MySQL数据库,修改datasource块和.env文件如下:
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
DATABASE_URL="mysql://user:password@localhost:3306/mydatabase"
其中user为数据库用户名,password为密码,mydatabase为数据库名称。
三、Prisma核心使用教程
3.1 数据模型定义
Prisma的核心是schema.prisma文件中的数据模型定义,模型对应数据库中的表,模型中的字段对应表中的列。下面以一个User用户模型和Post文章模型为例,展示如何定义关联模型。
// User模型:对应数据库中的users表
model User {
id Int @id @default(autoincrement()) // 主键,自增整数
name String // 用户名,字符串类型
email String @unique // 邮箱,唯一约束
age Int? // 年龄,可选整数(允许为空)
posts Post[] // 一对多关联:一个用户可以有多篇文章
createdAt DateTime @default(now()) // 创建时间,默认当前时间
}
// Post模型:对应数据库中的posts表
model Post {
id Int @id @default(autoincrement())
title String // 文章标题
content String? // 文章内容,可选
authorId Int // 外键,关联User模型的id
author User @relation(fields: [authorId], references: [id]) // 多对一关联
published Boolean @default(false) // 是否发布,默认false
createdAt DateTime @default(now())
}
字段属性说明
@id:标记该字段为主键。@default(autoincrement()):设置字段默认值为自增。@unique:添加唯一约束,确保字段值不重复。?:标记字段为可选,允许存储NULL值。@relation:定义模型之间的关联关系。
3.2 生成数据库表与客户端
定义好Schema后,需要执行迁移命令生成对应的数据库表结构,同时生成Python客户端代码。
- 创建迁移文件
执行以下命令,Prisma会根据Schema的变化生成迁移文件:bash prisma migrate dev --name init--name init表示给本次迁移命名为init,执行成功后,会在prisma/migrations目录下生成迁移历史文件,同时自动在数据库中创建User和Post表。 - 生成Python客户端
迁移完成后,Prisma会自动生成类型安全的Python客户端,无需手动编写。客户端文件默认生成在prisma目录下,可直接在Python代码中导入使用。
3.3 基础数据操作(CRUD)
Prisma客户端提供了简洁的API实现数据的增删改查,下面通过具体的Python脚本演示每个操作的使用方法。
3.3.1 连接数据库并初始化客户端
在Python脚本中,首先需要导入并初始化Prisma客户端,建立与数据库的连接:
# 导入Prisma客户端
from prisma import Prisma
# 初始化客户端
db = Prisma()
# 连接数据库
async def connect_db():
await db.connect()
# 关闭数据库连接
async def disconnect_db():
await db.disconnect()
由于Prisma的Python客户端基于异步IO设计,所有数据库操作都需要在异步函数中执行。
3.3.2 创建数据(Create)
使用create方法向数据库中插入单条数据,使用create_many方法批量插入多条数据。
单条数据插入
async def create_user():
# 连接数据库
await connect_db()
# 创建用户
user = await db.user.create(
data={
'name': '张三',
'email': '[email protected]',
'age': 25
}
)
# 打印创建的用户信息
print(f'创建用户成功:{user.id} - {user.name} - {user.email}')
# 关闭连接
await disconnect_db()
# 执行异步函数
import asyncio
asyncio.run(create_user())
执行上述代码后,会在User表中插入一条用户数据,user对象包含了数据库返回的完整用户信息,包括自动生成的id和createdAt字段。
批量数据插入
async def batch_create_users():
await connect_db()
# 批量创建3个用户
result = await db.user.create_many(
data=[
{'name': '李四', 'email': '[email protected]', 'age': 22},
{'name': '王五', 'email': '[email protected]', 'age': 28},
{'name': '赵六', 'email': '[email protected]'}
]
)
# result包含创建的记录数
print(f'批量创建用户成功,共创建 {result.count} 条记录')
await disconnect_db()
asyncio.run(batch_create_users())
create_many方法的返回值是一个包含count属性的对象,表示成功插入的记录数量。
3.3.3 查询数据(Read)
Prisma提供了丰富的查询方法,包括find_unique、find_first、find_many等,支持条件过滤、排序、分页和关联查询。
查询单条数据
使用find_unique方法根据唯一约束字段查询单条数据,例如根据邮箱查询用户:
async def find_user_by_email(email: str):
await connect_db()
# 根据邮箱查询用户(email字段有@unique约束)
user = await db.user.find_unique(
where={
'email': email
}
)
if user:
print(f'查询到用户:{user.name} - {user.age}')
else:
print('未查询到该用户')
await disconnect_db()
asyncio.run(find_user_by_email('[email protected]'))
使用find_first方法查询满足条件的第一条数据(无需唯一约束):
async def find_first_user():
await connect_db()
# 查询年龄大于20的第一个用户
user = await db.user.find_first(
where={
'age': {
'gt': 20
}
}
)
print(f'查询到用户:{user.name} - {user.age}')
await disconnect_db()
asyncio.run(find_first_user())
其中gt表示“大于”,Prisma支持的查询操作符还包括lt(小于)、gte(大于等于)、lte(小于等于)、contains(包含)等。
查询多条数据
使用find_many方法查询满足条件的所有数据,支持排序、分页和字段筛选:
async def find_all_users():
await connect_db()
# 查询所有用户,按创建时间降序排序,只返回name和email字段
users = await db.user.find_many(
select={
'name': True,
'email': True
},
order={
'createdAt': 'desc'
},
# 分页:跳过前1条,取2条
skip=1,
take=2
)
# 遍历打印用户信息
for user in users:
print(f'用户名:{user.name},邮箱:{user.email}')
await disconnect_db()
asyncio.run(find_all_users())
select参数用于指定返回的字段,order参数用于排序,skip和take参数用于实现分页功能。
关联查询
查询用户的同时,获取该用户发布的所有文章,使用include参数实现关联数据的加载:
async def find_user_with_posts(user_id: int):
await connect_db()
# 查询用户及其所有文章
user = await db.user.find_unique(
where={
'id': user_id
},
include={
'posts': True
}
)
if user:
print(f'用户:{user.name},发布的文章数:{len(user.posts)}')
for post in user.posts:
print(f'文章标题:{post.title},状态:{"已发布" if post.published else "未发布"}')
await disconnect_db()
# 假设用户id为1
asyncio.run(find_user_with_posts(1))
上述代码中,通过include={'posts': True},Prisma会自动查询该用户关联的所有Post数据,并封装到user.posts属性中。
3.3.4 更新数据(Update)
使用update方法更新单条数据,使用update_many方法批量更新多条数据。
单条数据更新
async def update_user_age(user_id: int, new_age: int):
await connect_db()
# 更新用户年龄
updated_user = await db.user.update(
where={
'id': user_id
},
data={
'age': new_age
}
)
print(f'用户更新成功,新年龄:{updated_user.age}')
await disconnect_db()
asyncio.run(update_user_age(1, 26))
update方法的where参数指定更新条件,data参数指定要更新的字段和值,返回值为更新后的完整数据对象。
批量数据更新
async def batch_update_posts():
await connect_db()
# 将所有未发布的文章标记为已发布
result = await db.post.update_many(
where={
'published': False
},
data={
'published': True
}
)
print(f'批量更新成功,共更新 {result.count} 篇文章')
await disconnect_db()
asyncio.run(batch_update_posts())
3.3.5 删除数据(Delete)
使用delete方法删除单条数据,使用delete_many方法批量删除多条数据。
单条数据删除
async def delete_user(user_id: int):
await connect_db()
# 删除指定用户
deleted_user = await db.user.delete(
where={
'id': user_id
}
)
print(f'删除用户成功:{deleted_user.name}')
await disconnect_db()
asyncio.run(delete_user(4))
批量数据删除
async def delete_unpublished_posts():
await connect_db()
# 删除所有未发布的文章
result = await db.post.delete_many(
where={
'published': False
}
)
print(f'批量删除成功,共删除 {result.count} 篇文章')
await disconnect_db()
asyncio.run(delete_unpublished_posts())
3.4 事务处理
事务是数据库操作的重要特性,用于保证多个操作的原子性(要么全部成功,要么全部失败)。Prisma客户端提供transaction方法实现事务处理。
例如,创建用户的同时,为该用户创建一篇文章,两个操作在同一个事务中执行:
async def create_user_and_post():
await connect_db()
try:
# 开启事务
async with db.transaction():
# 第一步:创建用户
user = await db.user.create(
data={
'name': '钱七',
'email': '[email protected]',
'age': 30
}
)
print(f'事务中创建用户:{user.name}')
# 第二步:为该用户创建文章
post = await db.post.create(
data={
'title': 'Prisma事务教程',
'content': 'Prisma的事务处理非常简单',
'authorId': user.id
}
)
print(f'事务中创建文章:{post.title}')
# 事务提交成功
print('用户和文章创建成功,事务已提交')
except Exception as e:
# 事务回滚
print(f'操作失败,事务已回滚,错误信息:{e}')
finally:
await disconnect_db()
asyncio.run(create_user_and_post())
在上述代码中,async with db.transaction()上下文管理器会自动管理事务的提交和回滚:如果上下文内的所有操作都成功执行,事务会自动提交;如果任何一个操作抛出异常,事务会自动回滚,确保数据一致性。
四、实际项目案例:简易博客系统
4.1 项目需求
构建一个简易的博客系统,实现以下功能:
- 用户注册和登录(简化版,不涉及密码加密)
- 创建、查询、发布博客文章
- 查询指定用户的所有文章
4.2 项目目录结构
simple_blog/
├── .env # 环境变量配置
├── schema.prisma # Prisma数据模型定义
└── blog.py # 业务逻辑代码
4.3 数据模型定义
schema.prisma文件的内容与第三部分的模型定义一致,包含User和Post两个关联模型。
4.4 业务逻辑实现
blog.py文件中实现具体的业务功能,代码如下:
from prisma import Prisma
import asyncio
# 初始化Prisma客户端
db = Prisma()
# 数据库连接与关闭工具函数
async def get_db():
await db.connect()
try:
yield db
finally:
await db.disconnect()
# 1. 用户注册功能
async def register_user(name: str, email: str, age: int = None):
async for db in get_db():
# 检查邮箱是否已存在
existing_user = await db.user.find_unique(where={'email': email})
if existing_user:
print(f'邮箱 {email} 已被注册')
return None
# 创建新用户
user = await db.user.create(
data={
'name': name,
'email': email,
'age': age
}
)
print(f'用户 {name} 注册成功,用户ID:{user.id}')
return user
# 2. 创建博客文章
async def create_article(title: str, content: str, author_id: int):
async for db in get_db():
# 检查作者是否存在
author = await db.user.find_unique(where={'id': author_id})
if not author:
print(f'作者ID {author_id} 不存在')
return None
# 创建文章
post = await db.post.create(
data={
'title': title,
'content': content,
'authorId': author_id
}
)
print(f'文章 {title} 创建成功,文章ID:{post.id}')
return post
# 3. 发布博客文章
async def publish_article(post_id: int):
async for db in get_db():
post = await db.post.update(
where={'id': post_id},
data={'published': True}
)
print(f'文章 {post.title} 已发布')
return post
# 4. 查询用户的所有已发布文章
async def get_user_published_posts(author_id: int):
async for db in get_db():
user = await db.user.find_unique(
where={'id': author_id},
include={
'posts': {
'where': {'published': True},
'order': {'createdAt': 'desc'}
}
}
)
if not user:
print(f'作者ID {author_id} 不存在')
return []
print(f'用户 {user.name} 的已发布文章:')
for post in user.posts:
print(f'- {post.title} | 创建时间:{post.createdAt}')
return user.posts
# 主函数:执行案例
async def main():
# 注册新用户
user = await register_user('小明', '[email protected]', 23)
if not user:
return
# 为用户创建文章
post = await create_article('Prisma实战教程', '本文介绍了Prisma的核心用法', user.id)
if not post:
return
# 发布文章
await publish_article(post.id)
# 查询用户已发布的文章
await get_user_published_posts(user.id)
# 运行主函数
if __name__ == '__main__':
asyncio.run(main())
4.5 运行结果
执行blog.py文件,控制台输出如下:
用户 小明 注册成功,用户ID:5
文章 Prisma实战教程 创建成功,文章ID:3
文章 Prisma实战教程 已发布
用户 小明 的已发布文章:
- Prisma实战教程 | 创建时间:2024-05-20 15:30:25
五、Prisma相关资源
5.1 PyPI地址
5.2 Github地址
5.3 官方文档地址
关注我,每天分享一个实用的Python自动化工具。

