我希望将我的数据库实现放在单独的模块或类中。但我正在努力解决一些细节问题。一个简单的例子:
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')
或选择任何其他文件名。我甚至可以在同一个程序中使用多个数据库实例,每个实例都有自己的文件。
但是,这种方法存在两个问题:
SqliteDatabase
)。为了解决这个问题,我在__init__()
方法中定义了Model类,然后使用self.User = User
创建了一个别名。我真的不喜欢这种方法(它只是感觉不像整洁的代码),但至少它是有效的。 @db.atomic()
装饰器,因为self
在类级别是未知的,我会在这里作为实例。所以这种方法看起来效果不好。有没有更好的方法来定义Model类,而不必先选择存储数据库的位置?
答案 0 :(得分:7)
如果您需要在运行时更改数据库驱动程序,那么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()
方法就足够了。
答案 1 :(得分:0)
现在我希望能够在运行时选择数据库文件。所以我 需要一种方法来定义Model类而无需定义 SqliteDatabase(' somefile')之前。我试图封装一切 在一个新的数据库类中,我可以在以后导入并创建一个 来自
的实例
Peewee使用元类来定义表的名称(Model.Meta.db_table
)和数据库(Model.Meta.database
)
在调用特定于模型的代码(创建表或DML语句)之前设置这些属性
答案 2 :(得分:0)
问题:我不能使用@ db.atomic()装饰器,因为在类级别不知道self
执行此操作,就像使用self.User
一样
我想知道atomic()
而不是atomic
,但是你告诉工作正常。
class Database:
def __init__(self, dbfile):
self.db = SqliteDatabase(dbfile)
...
@self.db.atomic()
def __add_user(self, name):
self.User.create(name=name).save()
self.add_user = __add_user
@self.db.atomic()
def __get_user(self, name):
return self.User.get(self.User.name == name)
self.get_user = __get_user