简体   繁体   中英

How to create a hybrid_property that incorporates split()?

Given the simple table:

class Result(Base):
    __tablename__ = "result"

    id_ = Column(Integer, primary_key=True, autoincrement=True)
    result = Column(String(20))

Where result records are of the form 6-1 , 7-5 etc.

I'd like to create a property that sums the integers in the result field, eg 6-1 would be 7 . I've tried the following:

@hybrid_property
def sum_games(self):
    return sum(int(s) for s in self.result.split("-"))

But I get the error:

Exception has occurred: AttributeError
Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Result.result has an attribute 'split'

I understand enough of Python to get that self.result isn't a string so I can't use the split() method. Is there a way to convert this to a string? I've tried str(self.result) but that returns Result.result .

Maybe there's another way to achieve the output I'm looking for?

Worth me mentioning that the result strings are actually a little more complicated than the examples above but I always need the split() method so I've simplified for this post.

Hybrid properties have two parts, a Python part and a SQL part, which is denoted with the decorator @sum_games.expression . If you don't specify that expression counterpart, the hybrid property itself is used in SQL as well. But .split() and all the other python functions are unknown there, so try the following instead:

@hybrid_property
def sum_games(self):
    return sum(int(s) for s in self.result.split("-"))

@sum_games.expression
def sum_games(cls):  # yes this is a class method for some reason
    sum_part_array = func.regexp_split_to_array(cls.result, '-')
    sum_parts = func.unnest(sum_part_array).alias("y")
    sum_clause = func.sum(cast(column("y"), Integer)

    return select([sum_clause]).select_from(sum_parts).as_scalar()

With translates to the SQL:

SELECT (SELECT SUM(y::int) FROM unnest(regexp_split_to_array(x, '-')) as y)
FROM (values ('6-1'), ('7-1')) as bla(x)

This works with PostgreSQL, if you use a different dialect, the same logic should hold with the equivalent functions

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM