【AI总结】在 Peewee 中基于 MySQL 实现“动态表名”——从连接到查询的完整实战
数据量太大,需要按年份、月份、用户 ID 等进行分表;表名在运行时才确定,无法提前写死在模型类中;但又想继续使用 Peewee 的 ORM 接口进行增删查改。问题来了:Peewee 的是类级属性,运行时无法修改。解决方案动态创建模型类,每个表名对应一个新类,完全复用 Peewee 的 ORM 能力。功能是否支持动态表名✅ 通过动态创建模型类ORM 接口✅ 完全保留自动建表✅事务支持✅ 复用 Pee
·
文章目录
在 Peewee 中基于 MySQL 实现“动态表名”——从连接到查询的完整实战
标签:Python、ORM、Peewee、MySQL、动态表名、分表、实战
一、前言
在使用 Peewee 操作 MySQL 时,有时我们会遇到这样的需求:
- 数据量太大,需要按年份、月份、用户 ID 等进行分表;
- 表名在运行时才确定,无法提前写死在模型类中;
- 但又想继续使用 Peewee 的 ORM 接口进行增删查改。
问题来了:Peewee 的 Meta.table_name
是类级属性,运行时无法修改。
解决方案:动态创建模型类,每个表名对应一个新类,完全复用 Peewee 的 ORM 能力。
二、环境准备
1. 安装依赖
pip install peewee pymysql
2. 创建数据库(以 MySQL 为例)
CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARSET utf8mb4;
三、连接 MySQL 并封装基础模型
import pymysql
from peewee import *
# 让 pymysql 兼容 MySQLdb
pymysql.install_as_MSQLdb()
# 创建数据库连接
db = MySQLDatabase(
'demo',
user='root',
password='123456',
host='127.0.0.1',
port=3306,
charset='utf8mb4'
)
# 公共基类,统一绑定数据库
class BaseModel(Model):
class Meta:
database = db
四、核心:动态模型工厂函数
def create_dynamic_model(table_name: str) -> type:
"""
根据表名动态创建 Peewee 模型类
"""
# 动态创建 Meta 类
Meta = type('Meta', (), {'table_name': table_name})
# 模型字段定义
attrs = {
'id': AutoField(primary_key=True),
'source_id': IntegerField(null=True),
'index_name_one': CharField(max_length=255, null=True),
'index_name_two': CharField(max_length=255, null=True),
'Meta': Meta,
'__module__': __name__,
}
# 动态类名,方便调试
class_name = f'IndexRecordPairs_{table_name}'
return type(class_name, (BaseModel,), attrs)
五、使用示例:动态建表 + 增删查改
# 假设我们按年份分表
table_2023 = create_dynamic_model('index_record_pairs_2023')
table_2024 = create_dynamic_model('index_record_pairs_2024')
# 自动建表(仅不存在时创建)
db.create_tables([table_2023, table_2024])
# 插入数据
table_2023.create(
source_id=1001,
index_name_one='GDP',
index_name_two='地区生产总值'
)
# 查询数据
for row in table_2023.select():
print(row.id, row.index_name_one, row.index_name_two)
# 更新数据
table_2023.update(index_name_two='全省GDP').where(table_2023.source_id == 1001).execute()
# 删除数据
table_2023.delete().where(table_2023.source_id == 1001).execute()
六、优化建议:缓存模型类避免重复创建
_MODEL_CACHE = {}
def get_dynamic_model(table_name: str) -> type:
if table_name not in _MODEL_CACHE:
_MODEL_CACHE[table_name] = create_dynamic_model(table_name)
return _MODEL_CACHE[table_name]
七、总结
功能 | 是否支持 |
---|---|
动态表名 | ✅ 通过动态创建模型类 |
ORM 接口 | ✅ 完全保留 |
自动建表 | ✅ db.create_tables() |
事务支持 | ✅ 复用 Peewee 事务 |
性能影响 | ✅ 极小,模型类可缓存 |
结论:
Peewee 虽然不支持“运行时改表名”,但借助 Python 的 type()
动态创建类,我们可以轻松实现 MySQL 动态表名 的需求,且代码简洁、可维护性强,非常适合分表、日志、审计等场景。
如需进一步扩展,可以结合:
- 分表策略(按年月、哈希、用户 ID);
- 自动迁移工具(如
pt-online-schema-change
); - 连接池(
playhouse.pool
)提升并发性能。
希望这篇博客能帮你在实际项目中灵活运用 Peewee!
更多推荐
所有评论(0)