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.

Reply via email to