After reading more documents i ended up using comparator for my hybrid property instead of expression. like: class JalaliDateComparator(Comparator): def operate(self, op, other): input_date = self.__clause_element__() g_date = other.togregorian()
return op(input_date, g_date) So far it seems working, but i'll consider your solution too. i'm not sure which way is best practice but i'm happy that i have two solutions :) Thanks for your reply. On Monday, August 24, 2015 at 7:24:26 AM UTC+4:30, Michael Bayer wrote: > > > On 8/22/15 4:30 PM, Mehdi wrote: > > Hi > I'm using latest sqlalchemy with an Oracle db backend. > I have a Date column which presents a *Gregorian date* in db. but i want > to query my table by a *Jalali date*. > So the hybrid_property to convert gregorian date into jalali date should > be like this, i think: > @hybrid_property > def jalali_date(self): > return jdatetime.date.fromgregorian(year=self.input_date.year, > month=self.input_date, > day=self.input_date.day) > > > i've tried different ways, but all of them ends with errors like: > AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' > object associated with MeasureData.input_date has an attribute 'year' > or > TypeError: an integer is required (got type InstrumentedAttribute) > > So i guess i have to get access to *instance value* of > *MeasureDate.input_date* at hybrid_property definition, but How? > Do i have to completely change my approach? > > > the hybrid allows a Python representation at the object level and a SQL > representation at the class level. Your error message involves the term > "InstrumentedAttribute", which suggests you are attempting to use this > hybrid at the class level (please provide full stack traces to make this > clearer). Your hybrid as defined only illustrates instance-level > conversions and there's not a simple way to do this conversion at the SQL > level especially in Oracle, unless you had some stored procedure which does > so. > > Therefore, you are probably looking for an in-Python value of a Jalali > date to be converted from the alternate calendar to the gregorian > (SQL-persisted) calendar *in python*, before it is sent to the database, > and converted back to Jalali *in Python* after being received from the > database as a result. For this, you want to build a custom type similar to > the "MyEpochType" illustrated at > http://docs.sqlalchemy.org/en/rel_1_0/core/custom_types.html#augmenting-existing-types > > - using this type will cause expressions like equality comparisons to > coerce the "value side" of the expression, e.g. the raw datetime object, as > according to your rules. You can then cause this particular type to be > used with your hybrid using type_coerce. Here's an example using most > features of hybrids: > > from sqlalchemy import * > from sqlalchemy.orm import * > from sqlalchemy.ext.declarative import declarative_base > from sqlalchemy.ext.hybrid import hybrid_property > import jdatetime > import datetime > > Base = declarative_base() > > > class JDate(TypeDecorator): > impl = Date > > def process_bind_param(self, value, dialect): > if value is not None: > value = jdatetime.date.togregorian(value) > return value > > def process_result_value(self, value, dialect): > if value is not None: > value = jdatetime.date.fromgregorian( > year=value.year, > month=value.month, > day=value.day) > return value > > > class A(Base): > __tablename__ = 'a' > id = Column(Integer, primary_key=True) > > input_date = Column(Date) > > @hybrid_property > def jalali_date(self): > return jdatetime.date.fromgregorian( > year=self.input_date.year, > month=self.input_date.month, > day=self.input_date.day) > > @jalali_date.expression > def jalali_date(cls): > return type_coerce(cls.input_date, JDate) > > @jalali_date.setter > def jalali_date(self, value): > self.input_date = jdatetime.date.togregorian(value) > > > e = create_engine("postgresql://scott:tiger@localhost/test", echo=True) > Base.metadata.drop_all(e) > Base.metadata.create_all(e) > > > a1 = A(jalali_date=jdatetime.date(1380, 8, 2)) > a2 = A(input_date=datetime.date(2001, 10, 24)) > > s = Session(e) > s.add_all([a1, a2]) > s.commit() > s.close() > > a1, a2 = s.query(A).filter_by(jalali_date=jdatetime.date(1380, 8, 2)).all() > > print a1.jalali_date, a2.jalali_date > print a1.input_date, a2.input_date > > > > in the output, we can see that jalali_date and input_date are consistent > from both ways of setting, both ways of matching: > > 1380-08-02 1380-08-02 > 2001-10-24 2001-10-24 > > > > > > > > > Thanks. > -- > 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+...@googlegroups.com <javascript:>. > To post to this group, send email to sqlal...@googlegroups.com > <javascript:>. > Visit this group at http://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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.