每个实例数据库的Peewee ORM类定义

时间:2017-12-12 19:29:37

标签: python peewee

我想为每个Peewee ORM实例提供不同的数据库文件。 Peewee使用嵌套的“Meta”类将数据库引擎分配给实例。

我的问题似乎归结为从内部类访问类实例属性。使用Peewee快速入门示例,这就是我想要在(破碎的)Python中实现的目标:

from peewee import *

class Person(Model):

    def __init__(self, database):
        self.database = database

    name = CharField()
    birthday = DateField()
    is_relative = BooleanField()

    class Meta:

        # The following is incorrect; I'm trying to access the instance
        # variable for the database filename string
        database = SqliteDatabase(Person.database)

# Create two instances with different databases:
john = Person('john-database.db')
jane = Person('jane-database.db')

我找到了一些关于嵌套类的一般答案,但很难将他们的课程翻译成这个特定的应用程序。感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

我认为简短的回答是“peewee并非真正为您的用例而设计”。但我玩了一下,虽然必须有一个更好的解决方案,但这里有一些工作。但这不是一个好主意,你不应该这样做。

首先,我们使用标准的peewee示例模型,除了我们使用Proxy类进行数据库连接:

from peewee import *
from playhouse import *

db = Proxy()


class Person(Model):

    name = CharField()
    birthday = DateField()
    is_relative = BooleanField()

    class Meta:
        database = db

假设我们在model.py中有这个。

现在,为了使这项工作,我们将需要model模块的两个实例,我们可以使用importlib模块获取(ab):

import importlib.util
import peewee
import sys

def load_module_as(modname, alias):
    mod_spec = importlib.util.find_spec(modname)
    mod = importlib.util.module_from_spec(mod_spec)
    mod_spec.loader.exec_module(mod)
    sys.modules[alias] = mod
    return mod

这允许我们加载model的两个单独的实例:

model1 = load_module_as('model', 'model1')
model2 = load_module_as('model', 'model2')

然后我们可以初始化两个不同的数据库:

model1.db.intitialize(pwee.SqliteDatabase('db1.db'))
model2.db.intitialize(pwee.SqliteDatabase('db2.db'))

虽然这种方式可以满足您的需求,但您始终需要对您的课程进行资格认证(model1.Personmodel2.Person)。

这是一个完整的例子,单元测试:

import datetime
import importlib.util
import os
import peewee
import shutil
import sys
import tempfile
import unittest


def load_module_as(modname, alias):
    mod_spec = importlib.util.find_spec(modname)
    mod = importlib.util.module_from_spec(mod_spec)
    mod_spec.loader.exec_module(mod)
    sys.modules[alias] = mod
    return mod

model1 = load_module_as('model', 'model1')
model2 = load_module_as('model', 'model2')


class TestDatabase(unittest.TestCase):
    def setUp(self):
        self.workdir = tempfile.mkdtemp('testXXXXXX')
        self.db1_path = os.path.join(self.workdir, 'db1.db')
        self.db1 = peewee.SqliteDatabase(self.db1_path)
        self.db1.connect()

        self.db2_path = os.path.join(self.workdir, 'db2.db')
        self.db2 = peewee.SqliteDatabase(self.db2_path)
        self.db2.connect()

        model1.db.initialize(self.db1)
        model2.db.initialize(self.db2)

        self.db1.create_tables([model1.Person])
        self.db2.create_tables([model2.Person])

    def test_different_instances(self):
        assert model1.db != model2.db

    def test_create_model1_person(self):
        p = model1.Person(name='testperson',
                          birthday=datetime.datetime.now().date(),
                          is_relative=True)
        p.save()

    def test_create_model2_person(self):
        p = model2.Person(name='testperson',
                          birthday=datetime.datetime.now().date(),
                          is_relative=True)
        p.save()

    def test_create_both(self):
        p1 = model1.Person(name='testperson',
                           birthday=datetime.datetime.now().date(),
                           is_relative=True)
        p2 = model2.Person(name='testperson',
                           birthday=datetime.datetime.now().date(),
                           is_relative=False)
        p1.save()
        p2.save()

        p1 = model1.Person.select().where(model1.Person.name == 'testperson').get()
        p2 = model2.Person.select().where(model2.Person.name == 'testperson').get()

        assert p1.is_relative
        assert not p2.is_relative

    def tearDown(self):
        self.db1.close()
        self.db2.close()
        shutil.rmtree(self.workdir)

if __name__ == '__main__':
    unittest.main(verbosity=2)

答案 1 :(得分:0)

我还找到了this thread一些可能的答案。