sqlalchemy: логическое выражение для hybrid_property - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть класс sqlalchemy, который представляет таблицу со столбцами FileID и SettlementDate.Я хочу создать гибридное свойство, чтобы сказать, является ли данный экземпляр максимальным FileID для его SettlementDate, и связанное выражение для использования при запросах.У меня успешно работает имущество, но я борюсь с выражением.Вот существующая модель:


class Hdr(model.Base):

    id = Column('ID', Integer, primary_key=True)
    file_id = Column('FileID', BIGINT, ForeignKey('FileRegister.Files.ID'))
    settlement_date = Column('SettlementDate', Date)

    @hybrid_property
    def is_latest(self):
        subquery = (
            object_session(self)
            .query(func.max(Hdr.file_id).label('file_id'))
            .group_by(Hdr.settlement_date)
            .subquery()
        )

        return (
            object_session(self)
            .query(func.count(Hdr.file_id).cast(Boolean))
            .filter(subquery.c.file_id==self.file_id)
            .scalar()
        )

Я хотел бы думать, что могу сделать что-то вроде:

subquery = (
    select((func.max(Hdr.file_id).label('file_id'), ))
    .group_by(Hdr.settlement_date)
    .alias('a')
)

s = select(
    case(
        whens=[
            (Hdr.file_id.in_(subquery), 1)
        ],
        else_=0
    )
)

Но это вызывает ошибку Boolean value of this clause is not defined.

Любая помощь будет принята с благодарностью!

Отслеживание следует:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\sql\selectable.py in __init__(self, columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)
   2889         try:
-> 2890             cols_present = bool(columns)
   2891         except TypeError:

c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\sql\elements.py in __bool__(self)
    515     def __bool__(self):
--> 516         raise TypeError("Boolean value of this clause is not defined")
    517 

TypeError: Boolean value of this clause is not defined

During handling of the above exception, another exception occurred:

ArgumentError                             Traceback (most recent call last)
<ipython-input-20-4946a4bf7faa> in <module>
     10             (Hdr.file_id.in_(subquery), 1)
     11         ],
---> 12         else_=0
     13     )
     14 )

<string> in select(columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)

<string> in __init__(self, columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)

c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\util\deprecations.py in warned(fn, *args, **kwargs)
    128                     )
    129 
--> 130             return fn(*args, **kwargs)
    131 
    132         doc = fn.__doc__ is not None and fn.__doc__ or ""

c:\Users\\venvs\insight\lib\site-packages\sqlalchemy-1.3.0b3-py3.7-win-amd64.egg\sqlalchemy\sql\selectable.py in __init__(self, columns, whereclause, from_obj, distinct, having, correlate, prefixes, suffixes, **kwargs)
   2891         except TypeError:
   2892             raise exc.ArgumentError(
-> 2893                 "columns argument to select() must "
   2894                 "be a Python list or other iterable"
   2895             )

ArgumentError: columns argument to select() must be a Python list or other iterable

1 Ответ

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

Проблема в

s = select(case(...))

Первый аргумент select() должен быть последовательностью элементов столбца или объектов предложения.Кажется, что SQLAlchemy в какой-то момент проверяет, является ли переданная последовательность пустой или нет, выполнив bool(columns).Решение состоит в том, чтобы просто обернуть его в последовательность, как вы это делали при создании subquery:

s = select([case(...)])

в "стороне Python" гибридного свойства вместо подсчета, если максимальное file_id любого settlement_date соответствует экземпляру, который вы можете отфильтровать по settlement_date экземпляра и проверить по максимуму:

class Hdr(model.Base):

    @hybrid_property
    def is_latest(self):
        max_file_id = (
            object_session(self)
            .query(func.max(Hdr.file_id))
            .filter(Hdr.settlement_date == self.settlement_date)
            .scalar()
        )

        return max_file_id == self.file_id

В выражении вам не нужно оборачивать логическое выражение вскалярный подзапрос, но возвращает само логическое выражение:

    @is_latest.expression
    def is_latest(cls):
        hdr_alias = aliased(Hdr)
        subquery = (
            select([func.max(hdr_alias.file_id)])
            .group_by(hdr_alias.settlement_date)
        )

        return cls.file_id.in_(subquery)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...