Наследование SQLAlchemy, основанное на том, существуют ли данные в другой таблице - PullRequest
1 голос
/ 22 октября 2011

У меня есть две устаревшие таблицы, которые я хотел бы использовать декларативную SQLAlchemy для доступа к данным.

Order:
order_id
is_processed

FooData:
foo_id
order_id

Заказ может иметь или не иметь FooData, и я хотел бы провести различие между двумя типами заказов, используя декларативные модели SQLAlchemy.

Проблема, которую я имею в виду, заключается в следующем.

  • Как мне установить такие отношения? В идеале у меня было бы два класса Order и FooOrder, где у Order нет FooData, а у FooOrder есть FooData.
  • Я должен запросить оба типа (Order и FooOrder) вместе на основе is_processed и обрабатывать их по-разному в зависимости от того, является ли это Order или FooOrder. Как мне сделать запрос в этом случае?

1 Ответ

0 голосов
/ 24 октября 2011

Если вы можете изменить БД, то просто добавьте один столбец дискриминатора , установите значение этого столбца в правильное значение (порядок | foodata) в зависимости от того, для него существует foodata, сделайте его NOT NULL и настройте простое наследование объединенных таблиц.

Если вы не можете изменить базу данных (добавить столбец дискриминатора), и у вас есть только простые Модель с 2 таблицами, как вы показываете, тогда я бы не использовал наследование, а скорее 1-1 отношения.

Определение модели:

class Order(Base):
    __tablename__ = 'order'
    __table_args__ = {'autoload': True}

class FooData(Base):
    __tablename__ = 'foo_data'
    __table_args__ = {'autoload': True}
    # @note: you need next line only if your DB does not have FK defined
    #__table_args__ = (ForeignKeyConstraint(['order_id'], ['order.order_id']), {'autoload': True})

# define 1-[0..1] relationship from Order to FooData with eager loading
Order.foodata = relationship(FooData, uselist=False, lazy="joined", backref="order")

Добавление новых объектов:

ord = Order(); ord.is_processed = False
session.add(ord)
ord = Order(); ord.is_processed = False
foo = FooData(); foo.someinfo = "test foo created from SA"
ord.foodata = foo
session.add(ord)
session.commit()

Запрос: все основано на is_processed:

qry = session.query(Order).filter(Order.is_processed == False)
for ord in qry:
    print ord, ord.foodata

A la Полиморфизм:

Вы даже можете реализовать методы на Order и FooData таким образом, чтобы Казалось бы, они на самом деле используют наследование:

class Order(Base):
    # ...
    def process_order(self):
        if self.foodata:
            self.foodata.process_order()
        else:
            print "processing order: ", self

class FooData(Base):
    # ...
    def process_order(self):
        print "processing foo_data: ", self
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...