I'm not sure what I am doing wrong. I have read in other questions that InstrumentedAttribute is something to do with a relationship, but if you look at my code below, start_date is not a relationship column. When I try to use self.start_date or self.start_time in the start_datetime() property, they are both sqlalchemy.orm.attributes.InstrumentedAttribute objects and I can't find any way to get a date or time. I am using Python 3.4.3, SQLAlchemy 1.0.12, psycopg2 2.6.1, and postgresql 9.3.12
Base = declarative_base()
class OnetimeReservation(Base):
__tablename__ = 'OnetimeReservation'
id = Column(Integer, primary_key=True, autoincrement=True)
resource_id = Column(Integer, ForeignKey('Resource.id', ondelete='CASCADE', onupdate='CASCADE'))
job_id = Column(Integer, nullable=True)
start_date = Column(Date)
start_time = Column(Time, nullable=True)
duration = Column(Integer, nullable=True)
date_created = Column(DateTime, server_default=text('CURRENT_TIMESTAMP'))
created_by = Column(String(128), server_default=text('CURRENT_USER'))
date_last_modified = Column(DateTime, server_default=text('CURRENT_TIMESTAMP'), server_onupdate=text('CURRENT_TIMESTAMP'))
last_modified_by = Column(String(128), server_default=text('CURRENT_USER'), server_onupdate=text('CURRENT_USER'))
resource = relationship('Resource')
@hybrid_property
def start_datetime(self):
return datetime.combine(self.start_date, self.start_time)
After a more thorough reading of the docs regarding hybrid_property, I think I know what's going on. The reason it is called a "hybrid" property is that is may be called with an instance of the class, or the class itself. When used as filter parameter, it is called with the class itself and, it appears that there is an attempt to convert the code to SQL. There is a way to provide a separate implementation for @start_time.expression that will get called with the class. Thanks to everyone's help, I was able to work out a simple implementation that seems to work. Here is the result:
@hybrid_property
def start_datetime(self):
if not self.start_time: # start_time can be null
return None
return datetime.combine(self.start_date, self.start_time)
@start_datetime.expression
def start_datetime(cls):
return cls.start_date + cls.start_time
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With