2015-04-14 2 views
4

Поддерживает ли SQLAlchemy составные типы PostgreSQL (http://www.postgresql.org/docs/devel/static/rowtypes.html)? Я нашел, что у него что-то похожее (sqlalchemy.orm.composite), но, насколько я вижу, это недостаточно для моей цели.SQLAlchemy composite type

Я хотел бы сделать отдельный тип, например Amount, имеющего value и currency, а затем иметь возможность обратиться к нему несколько раз, и, возможно, несколько раз из того же класса:

class Transfer(base): 
    __tablename__ = "transfer" 
    source_amount = Column(Amount) 
    target_amount = Column(Amount) 

Все примеры, которые я видел (например, this one), требуют от меня указать имена столбцов, что делает такой подход невозможным (имена столбцов будут сталкиваться).

Кроме того, я бы предпочел иметь один столбец за штуку вместо двух (поскольку value на самом деле не имеет смысла без currency, я бы предпочел, чтобы база данных заботилась о том, чтобы никогда не отделять их или смешивать). Кажется, Postgres может это сделать, мне просто нужен способ объяснить SQLAlchemy, что мне нужно. Я пробовал читать http://docs.sqlalchemy.org/en/latest/core/custom_types.html, но, похоже, он фокусируется на увеличении существующих типов, а не на создании новых композиций (я не знаю, что положить под impl).

Возможно, я должен отпустить SQLAlchemy и напрямую связаться с psycopg2? Он имеет функцию psycopg2.extras.register_composite, но как только я это сделаю, я до сих пор не знаю, как убедить SQLAlchemy распознать регистрацию. Мне, вероятно, придется каким-то образом передать курсор из psycopg2 в SQLAlchemy, но я не знаю, как это сделать.

ответ

0

sqlalchemy не поддерживает композитные типы postgresql изначально.

Однако sqlalchemy_utils поддерживает композитные типы postgresql изначально.

Вот пример из их документации:

from collections import OrderedDict 

import sqlalchemy as sa 
from sqlalchemy_utils import CompositeType, CurrencyType 

class Account(Base): 
    __tablename__ = 'account' 
    id = sa.Column(sa.Integer, primary_key=True) 
    balance = sa.Column(
     CompositeType(
      'money_type', 
      [ 
       sa.Column('currency', CurrencyType), 
       sa.Column('amount', sa.Integer) 
      ] 
     ) 
    ) 

Использование:

session.query(Account).filter(Account.balance.amount > 5000)