如何将Peewee ORM完整封装到单个类中?
解决Peewee ORM封装到单个类中的问题
你遇到的核心问题是嵌套类Meta无法直接访问外部Database实例的self——因为Meta作为Person的内部类,它的作用域和外部Database的实例作用域是隔离的,直接写self.db会被Python认为是Meta类自身的属性(但Meta并没有被实例化,也没有这个属性),所以报错。
下面提供一种简洁的解决方案,既能把所有逻辑封装到Database类内部,又能正常使用Peewee的功能:
完整可运行代码
from peewee import * from datetime import date class Database: def __init__(self, database_file='test.sqlite'): # 初始化数据库连接 self.db = SqliteDatabase(database_file) # 用局部变量保存数据库引用,让嵌套的Meta类能访问到 db_ref = self.db # 定义Person模型(嵌套在Database类内部) class Person(Model): name = CharField(unique=True) birthday = DateField() class Meta: database = db_ref # 使用局部变量db_ref,避免self作用域问题 table_name = 'people' # 可选:指定表名 # 将模型类挂载到实例上,方便内部方法调用 self.Person = Person # 自动创建表(如果不存在) self._create_tables() def _create_tables(self): """内部方法:创建所需数据表""" with self.db: self.db.create_tables([self.Person], safe=True) def add_person(self, name: str, birthday: date): """添加/更新Person数据""" # 使用get_or_create避免重复创建 person, created = self.Person.get_or_create( name=name, defaults={'birthday': birthday} ) if not created: person.birthday = birthday person.save() return person def get_person(self, name: str): """根据姓名查询Person""" try: return self.Person.get(self.Person.name == name) except self.Person.DoesNotExist: return None def close(self): """关闭数据库连接""" if not self.db.is_closed(): self.db.close() # 使用示例 if __name__ == '__main__': db = Database('people.db') # 添加数据 db.add_person('Alice', date(1990, 1, 1)) # 查询数据 alice = db.get_person('Alice') if alice: print(f"姓名:{alice.name},生日:{alice.birthday}") # 关闭连接 db.close()
关键解决思路
用局部变量传递数据库引用:
在__init__中定义db_ref = self.db,嵌套的Person.Meta可以访问到这个局部变量(Python闭包特性),从而正确绑定数据库。将模型类挂载到实例属性:
把定义好的Person类赋值给self.Person,这样类内部的其他方法(比如add_person、get_person)就能直接调用这个模型类。封装数据库操作:
将数据的增、查、表创建、连接关闭等逻辑都封装到Database类内部,对外只暴露简洁的接口。
内容的提问来源于stack exchange,提问作者Ulrich
相关产品推荐
相关产品推荐

