SQLAlchemy hybrid properties not being returned by SimpleIO service


#1

I have an SQLAlchemy model class with hybrid properties, such as this:

class Room(Base):
    __tablename__ = 'room'

    id = Column(Integer, primary_key=True)
    floor_no = Column(Integer, nullable=False)
    room_no = Column(Integer, nullable=False)
    sgl_beds = Column(Integer, default=0, index=True)
    dbl_beds = Column(Integer, default=0, index=True)
    supplement = Column(Float, default=0, nullable=False)
    deleted = Column(DateTime, default=None)

    def __repr__(self):
        return "<Room(id='%s', number='%s', accommodates='%s')>" % (
            self.id, self.number, self.accommodates)

    @hybrid_property
    def accommodates(self):
        return self.sgl_beds + self.dbl_beds * 2

    @hybrid_property
    def number(self):
        return '%d%02d' % (self.floor_no, self.room_no)

Then I have a service that uses SimpleIO to get an element from the table, such as this:

class Get(Service):

    class SimpleIO:
        input_required = ('id')
        output_optional = ('id', 'floor_no', 'room_no', 'name', 'sgl_beds',
                           'dbl_beds', 'supplement', 'code', 'accommodates',
                           'number', 'deleted')

    def handle(self):
        conn = self.kvdb.conn.get('app:database:connection')
        id_ = self.request.input.id

        with closing(self.outgoing.sql.get(conn).session()) as session:
            result = session.query(Room).\
                filter(and_(Room.id == id_, Room.deleted.is_(None))).\
                one_or_none()

            if result:
                self.response.status_code = OK
                self.response.payload = result
            else:
                self.response.status_code = NOT_FOUND
                self.response.payload = ''

If I use self.logger.info() to print the content of result, then the accommodates and number attributes are there. If I use self.logger.info() to print the content of self.response.payload after result has been assigned to it, then the accommodates and number attributes are not there.

What am I doing wrong?

Just incidentally, I am using output_optional to list the fields of the model to be returned because we may receive an id that does not exist or that has been deleted. Not sure if this is the way to go.


#2

About the result object, the one returned from SQLAlchemy, can you tell me what its ._sa_class_manager.keys() method returns, that is, what is the output of the below? This is the call that establishes which output keys will be produced.

self.logger.info(result._sa_class_manager.keys())

I’m not sure what you mean by returning id in output_optional if it is optional on input?

Also, you may want to keep the SQL connection’s name in user_config rather than in Redis - in this way you will save TCP overhead of calling Redis. Values from INI files can be updated them in run-time without restarts. What you are doing will work fine, I’m just adding it so that you know.

https://zato.io/docs/progguide/service-local-config.html#ini-files


#3

The output is:

['code', 'sgl_beds', 'room_no', 'floor_no', 'deleted', 'supplement', 'dbl_beds', 'id', 'name']

So, no, the hybrid properties accommodates and number are not there :frowning_face:


#4

id is part of input_required as it is a required parameter. But I was talking about output_optional, which contains the list of all the attributes of the model. I am not sure whether I should be using:

output_optional = ('id', 'floor_no', 'room_no', 'name', 'sgl_beds', 'dbl_beds',
                   'supplement', 'code', 'accommodates', 'number', 'deleted')

Or:

output_required = ('id', 'floor_no', 'room_no', 'name', 'sgl_beds', 'dbl_beds',
                   'supplement', 'code', 'accommodates', 'number', 'deleted')

I am asking because I may receive an id for a record that does not exist, so I would return 404 Not Found. Therefore I would not be returning the required attributes id, floor_no, room_no, etc.


#5

Yes, I agree. I started playing with Redis and… well, I had to do something with it. :smile: But you are very right :+1: