Как динамически создавать объекты с помощью PonyORM? - PullRequest
0 голосов
/ 12 февраля 2019

Я хотел бы создать объекты БД в Pony ORM с помощью заводского метода, поэтому избегайте дублирования кода для похожих таблиц.

Вот мой не полностью рабочий минимальный пример:

from pony.orm import *


def factory(db, tablename):
    class TableTemplate(db.Entity):
        _table_ = tablename
        first_name = Required(str)
        last_name = Required(str)
        composite_index(first_name, last_name)
    return TableTemplate


db = Database(provider='sqlite', filename=':memory:')
Table1 = factory(db, "TABLE_1")

# the following line produces the exception:
#    pony.orm.core.ERDiagramError: Entity TableTemplate already exists
Table2 = factory(db, "TABLE_2")

db.generate_mapping(create_tables=True)
with db_session:
    Table1(first_name="foo", last_name="bar")

Исключение можно обойти, создав класс с динамическим именем, используя type, но это не очень хорошо работает с composite_index ...

Есть ли хороший способ создать фабрику таблиц с Pony ORM?

1 Ответ

0 голосов
/ 12 февраля 2019

Вот мой взгляд на фабрику ваших классов:

def factory(db, tablename):
    fields = {
        '_table': tablename,
        'first_name': Required(str)
        # rest of the fields
    }
    table_template = type(tablename.capitalize(),(db.Entity,),fields)
    return table_template

Это создаст класс, используя заглавные буквы в tablename и установив дескрипторы.Я не уверен насчет метаклассов, хотя

ОБНОВЛЕНИЕ НА composite_index ВЫПУСК

composite_index использует некоторые довольно неясные функции, вызывая этот метод:

def _define_index(func_name, attrs, is_unique=False):
    if len(attrs) < 2: throw(TypeError,
        '%s() must receive at least two attributes as arguments' % func_name)
    cls_dict = sys._getframe(2).f_locals
    indexes = cls_dict.setdefault('_indexes_', [])
    indexes.append(Index(*attrs, is_pk=False, is_unique=is_unique))

Небольшой эксперимент показывает, что вы можете выполнить то же самое, добавив поле самостоятельно.Таким образом, наша фабричная fields переменная выглядит следующим образом:

fields = {
        '_table': tablename,
        'first_name': Required(str),
        '_indexes_':[Index(('first_name','last_name'),is_pk=False,is_unique=False)]
        # rest of the fields
    }

Попробуйте и дайте мне знать.

ОБНОВЛЕНИЕ НА ЭКСПЕРИМЕНТЕ OP

Окончательный код будет выглядеть примерно так:

from pony.orm import *
from pony.orm.core import Index
def factory(db, tablename):
    fields = {
        '_table': tablename,
        'first_name': Required(str)
        # rest of the fields
    }
    fields['_indexes_'] = [Index(fields['first_name'],fields['last_name'],is_pk=False,is_unique=False)]
    table_template = type(tablename.capitalize(),(db.Entity,),fields)
    return table_template
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...