我希望将我的数据库实现放在一个单独的模块或类中.但我正在努力解决一些细节问题.一个简单的例子:
from peewee import *
db = SqliteDatabase(':memory:')
class BaseModel(Model):
class Meta:
database = db
class User(BaseModel):
name = CharField()
db.connect()
db.create_tables([User,])
db.commit()
@db.atomic()
def add_user(name):
User.create(name=name).save()
@db.atomic()
def get_user(name):
return User.get(User.name == name)
到目前为止,这工作正常.我可以在这里实现我的数据库接口并将其作为模块导入.
现在我希望能够在运行时选择数据库文件.所以我需要一种方法来定义Model类,而不需要先定义SqliteDatabase(‘somefile’).我试图将所有内容封装在一个新的Database类中,稍后我可以从中导入并创建一个实例:
from peewee import *
class Database:
def __init__(self, dbfile):
self.db = SqliteDatabase(dbfile)
class BaseModel(Model):
class Meta:
database = self.db
class User(BaseModel):
name = CharField()
self.User = User
self.db.connect()
self.db.create_tables([User,])
self.db.commit()
@self.db.atomic() # Error as self is not known on this level
def add_user(self, name):
self.User.create(name=name).save()
@self.db.atomic() # Error as self is not known on this level
def get_user(self, name):
return self.User.get(self.User.name == name)
现在我可以调用例如database = Database(‘database.db’)或选择任何其他文件名.我甚至可以在同一个程序中使用多个数据库实例,每个实例都有自己的文件.
但是,这种方法存在两个问题:
>在定义Model类之前,我仍然需要指定数据库驱动程序(SqliteDatabase).为了解决这个问题,我在__init __()方法中定义了Model类,然后使用self.User = User创建了一个别名.我真的不喜欢这种方法(它只是感觉不像整洁的代码),但至少它是有效的.
>我不能使用@ db.atomic()装饰器,因为在类级别不知道self,我会在这里做一个实例.
因此,这种类方法似乎不能很好地工作.有没有更好的方法来定义Model类,而不必先选择存储数据库的位置?
最佳答案 如果您需要在运行时更改数据库驱动程序,那么
Proxy是一种可行的方法
# database.py
import peewee as pw
proxy = pw.Proxy()
class BaseModel(pw.Model):
class Meta:
database = proxy
class User(BaseModel):
name = pw.CharField()
def add_user(name):
with proxy.atomic() as txn:
User.create(name=name).save()
def get_user(name):
with proxy.atomic() as txn:
return User.get(User.name == name)
从现在开始,每次加载模块时,都不需要初始化数据库.相反,您可以在运行时初始化它,并在多个之间切换,如下所示
# main.py
import peewee as pw
import database as db
sqlite_1 = pw.SqliteDatabase('sqlite_1.db')
sqlite_2 = pw.PostgresqlDatabase('sqlite_2.db')
db.proxy.initialize(sqlite_1)
sqlite_1.create_tables([db.User], safe=True)
db.add_user(name="Tom")
db.proxy.initialize(sqlite_2)
sqlite_2.create_tables([db.User], safe=True)
db.add_user(name="Jerry")
但如果连接是唯一重要的事情,那么init()
方法就足够了.