Передать параметр базы данных в метакласс peewee

Я использую peewee для управления операциями CRUD в базе данных Postgres.

В документации проекта подключение к базе данных и создание ORM должно быть настроено через класс Meta, который должны наследовать другие типы ORM.

from peewee import *
db = PostgresqlDatabase('table', **{})

class BaseModel(Model):
    class Meta:
        database = db
class Product(BaseModel):
    name = CharField(unique=True)

Я хотел бы иметь возможность инкапсулировать эту настройку в класс Persistence, как показано ниже (чтобы не создавать какие-либо глобальные переменные):

class Persistence():
    db = None

    class BaseModel(Model):
        class Meta:
            database = Persistence.db
    class Product(BaseModel):
        name = CharField(unique=True)

    def __init__(self):
        self.db = PostgresqlDatabase('table', **{})

К сожалению, это не работает с:

AttributeError: type object 'Persistence' has no attribute 'db'

Я не думаю, что это будет работать так, как ожидалось (не считая AttributeError), потому что даже если переменная находилась в области видимости во время создания BaseModel, она была бы None и не изменялась при создании экземпляра класса Persistence.

  1. Есть ли способ правильно определить область действия переменной db, чтобы она использовала атрибут класса для Persistence?
  2. Могу ли я передать это db соединение с peewee через другой механизм?

person James Taylor    schedule 04.06.2018    source источник


Ответы (2)


Ваша проблема смешивает две отдельные проблемы. Область видимости Python и инициализация базы данных Peewee. Было бы полезно, если бы вы четко определили, в чем именно заключается проблема.

Что касается части вашего вопроса, вы, вероятно, захотите отложить инициализацию базы данных. Для этого вы создаете заполнитель объекта базы данных или используете Proxy в зависимости от того, насколько поздно вы хотите отложить что-либо.

Пример отложенной инициализации:

db = SqliteDatabase(None)

class BaseModel(Model):
    class Meta:
        database = db

# Declare other models as subclasses of BaseModel, e.g.
class Foo(BaseModel):
    data = TextField()

class Persistence(object):
    def __init__(self, db_file):
        db.init(db_file)

В качестве альтернативы вы можете использовать прокси-сервер, который описан здесь: http://docs.peewee-orm.com/en/latest/peewee/database.html#dynamically-defining-a-database

person coleifer    schedule 12.06.2018

Вы можете использовать контексты выполнения «Использование» для динамических соединений с БД. Например, у меня есть что-то вроде этого:

from peewee import *
from playhouse.shortcuts import RetryOperationalError

from config import settings

class RetryMySQLDatabase(RetryOperationalError, MySQLDatabase):
    pass

db_connection = {}
for conn in settings.DB:
    dbs = settings.DB[conn]
    db_connection[conn] = RetryMySQLDatabase(
                                dbs["DB_NAME"], 
                                host=dbs["DB_HOST"], 
                                user=dbs["DB_USER"], 
                                password=dbs["DB_PASS"]
                            )

db = db_connection["default"] #if you don't want to have default connection, you can make use of Proxy() here

class BaseModel(Model):
    class Meta:
        database = db

class Booking(BaseModel):
    id = BigIntegerField(db_column='ID', primary_key=True)
    name = CharField(db_column='NAME', null=True)

И при использовании класса модели вы можете указать, какое соединение с БД использовать:

with Using(db_connection["read_only"], [Booking]):
    booking_data = Booking.get(Booking.id == 123)

Ссылка:

Контекст выполнения «Использование»: http://docs.peewee-orm.com/en/2.10.2/peewee/database.html?highlight=re#using-multiple-базыданных

Класс Proxy: http://docs.peewee-orm.com/en/latest/peewee/database.html#dynamically-defining-a-database

person Vinayak Hegde    schedule 08.06.2018
comment
Ссылки на устаревший API. - person coleifer; 12.06.2018