如何在自定义路径创建Peewee数据库并在Meta类中正确引用
问题原因
代码失效的核心是两点:
- 模型
Meta类中引用的db是全局作用域变量,create_database函数内新建的db属于函数局部变量,和模型绑定的数据库实例不是同一个对象,后续建表、读写操作都无法命中目标数据库 - 未在执行表操作前显式初始化数据库连接,容易触发连接未定义的报错
可行实现
两种常用方案,根据业务场景选择即可。
方案1:全局占位初始化,运行时绑定路径
适合数据库路径在程序启动时才确定、单数据库实例的场景:
import os from peewee import Model, SqliteDatabase # 先创建全局db占位实例,暂不指定存储路径 db = SqliteDatabase(None) class Domain(Model): # 自定义字段按业务需求补充 class Meta: database = db class Event(Model): # 自定义字段按业务需求补充 class Meta: database = db class State(Model): # 自定义字段按业务需求补充 class Meta: database = db def create_database(path: str, start_block: int): # 给全局db实例绑定实际存储路径 db.init(os.path.join(path, "db")) # 建立连接后再执行表操作 db.connect() db.create_tables([Domain, Event, State]) if State.select().count() == 0: State.create(height=start_block) # 操作完成后可按需关闭连接,也可通过上下文管理器自动管理连接生命周期 # db.close()
方案2:动态绑定模型到数据库实例
适合多数据库动态切换的场景,不需要提前初始化全局db:
import os from peewee import Model, SqliteDatabase # 定义基础模型类,暂不绑定数据库 class BaseModel(Model): class Meta: database = None class Domain(BaseModel): # 自定义字段按业务需求补充 pass class Event(BaseModel): # 自定义字段按业务需求补充 pass class State(BaseModel): # 自定义字段按业务需求补充 pass def create_database(path: str, start_block: int): db = SqliteDatabase(os.path.join(path, "db")) db.connect() # 将所有模型临时绑定到当前新建的数据库实例 db.bind([Domain, Event, State]) db.create_tables([Domain, Event, State]) if State.select().count() == 0: State.create(height=start_block)
注意点
- 所有建表、增删改查操作必须在
db.connect()执行完成、连接建立成功后运行,否则会抛出连接不存在的异常 create_tables方法默认不会覆盖路径下已存在的同名表,不会造成已有数据丢失- 写入操作建议包裹在事务中,避免程序异常导致数据不一致:
if State.select().count() == 0: with db.atomic(): State.create(height=start_block)
内容的提问来源于stack exchange,提问作者BigP
相关产品推荐
相关产品推荐

