>
> User.firstname is not the value from any particular row - it's the
> (ORM-level) column object.


It's a little abstruse here that a ORM-level instrumented column object,
such as User.firstname works, but a true Column object, such as
User.__table__.c.firstname doesn't. Maybe I misunderstood your comment here?

On Mon, Oct 3, 2016 at 1:40 AM, Jinghui Niu <niujing...@gmail.com> wrote:

> Thank you Simon. Your explanation helps me understand this quite a lot.
> Sometimes the documentation is so terse that only when you fully understand
> the subject then you can understand it by reading it:) But still if I want
> to implement this hybrid property from the query level, how would you
> suggest modify my current code? Or maybe you could please point out a link
> to where I can explore further on the python to SQL transition? Thank you
> so much.
>
> Jinghui
>
> On Mon, Oct 3, 2016 at 1:27 AM, Simon King <si...@simonking.org.uk> wrote:
>
>> On Mon, Oct 3, 2016 at 7:17 AM, Jinghui Niu <niujing...@gmail.com> wrote:
>> > I have a ledger table and a corresponding python class. I defined the
>> model
>> > using SQLAlchemy, as follows,
>> >
>> > class Ledger(Base):
>> >     __tablename__ = 'ledger'
>> >
>> >     currency_exchange_rate_lookup = {('CNY', 'CAD'): 0.2}
>> >
>> >     amount = Column(Numeric(10, 2), nullable=False)
>> >     currency = Column(String, nullable=False)
>> >     payment_method = Column(String)
>> >     notes = Column(UnicodeText)
>> >
>> >     @hybrid_property
>> >     def amountInCAD(self):
>> >         if self.currency == 'CAD':
>> >             return self.amount
>> >         exchange_rate = self.currency_exchange_rate_lo
>> okup[(self.currency,
>> > 'CAD')]
>> >         CAD_value = self.amount * Decimal(exchange_rate)
>> >         CAD_value = round(CAD_value, 2)
>> >         return CAD_value
>> >
>> >     @amountInCAD.expression
>> >     def amountInCAD(cls):
>> >         amount = cls.__table__.c.amount
>> >         currency_name = cls.__table__.c.currency
>> >         exchange_rate = cls.currency_exchange_rate_loo
>> kup[(currency_name,
>> > 'CAD')]
>> >         return case([
>> >             (cls.currency == 'CAD', amount),
>> >         ], else_ = round((amount * Decimal(exchange_rate)),2))
>> >
>> > Now as you can see, I want to create a hybrid property called
>> "amountInCAD".
>> > The Python level getter seems to be working fine. However the SQL
>> expression
>> > doesn't work.
>> >
>> > Now if I run a query like this:
>> >
>> >>>>db_session.query(Ledger).filter(Ledger.amountInCAD > 1000)
>> >
>> > SQLAlchemy gives me this error:
>> >
>> >   File "ledger_db.py", line 43, in amountInCAD
>> >     exchange_rate = cls.currency_exchange_rate_lookup[(currency_name,
>> > 'CAD')]
>> > KeyError: (Column('currency', String(), table=<ledger>, nullable=False),
>> > 'CAD')
>> >
>> > I've researched SQLAlchemy's online documentation regarding hybrid
>> > property.http://docs.sqlalchemy.org/en/latest/orm/mapped_
>> sql_expr.html#using-a-hybrid
>> > Comparing my code to the example code, I don't understand why mine
>> doesn't
>> > work. If in the official example, cls.firstname can refer to a column of
>> > value, why in my code the cls.__table__.c.currencyonly returns a Column
>> not
>> > its value?
>>
>> Forget about using this in a query for a second. For example, open a
>> python shell, import your class, and type "Ledger.amountInCAD". This
>> will trigger the same exception. There's no way that
>> cls.__table__.c.currency can *ever* return a value from a specific
>> row, because you are accessing it from the *class*, which isn't
>> related to any specific row.
>>
>> I assume the example in the docs you are referring to is this one:
>>
>>     @hybrid_property
>>     def fullname(self):
>>         return self.firstname + " " + self.lastname
>>
>> In this example, "User.fullname" is precisely equivalent to:
>>
>>   User.firstname + " " + User.lastname
>>
>> User.firstname is not the value from any particular row - it's the
>> (ORM-level) column object. The result of that expression is another
>> SQL expression.
>>
>> Sorry, that's probably not a very good explanation. Has it made it any
>> clearer?
>>
>> Simon
>>
>> --
>> You received this message because you are subscribed to a topic in the
>> Google Groups "sqlalchemy" group.
>> To unsubscribe from this topic, visit https://groups.google.com/d/to
>> pic/sqlalchemy/7AsxiTT3Dtc/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to
>> sqlalchemy+unsubscr...@googlegroups.com.
>> To post to this group, send email to sqlalchemy@googlegroups.com.
>> Visit this group at https://groups.google.com/group/sqlalchemy.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to