Skip to content Skip to sidebar Skip to footer

Can't Set Attribute On Result Objects In Sqlalchemy Flask

I encounter a problem with Flask-SQLAlchemy, I can set the attribute of the objects in place_collections, but when I want to set the attribute for objects in places, an error occur

Solution 1:

place_collections = Place.query.filter_by(county='BKK') will return you a collection of Place objects. This is analogous to session.query(Place).filter_by(county='BKK') in plain vanilla SQLAlchemy.

However, from the SQLAlchemy docs:

The Query also accepts ORM-instrumented descriptors as arguments. Any time multiple class entities or column-based entities are expressed as arguments to the query() function, the return result is expressed as tuples

The key point being that when you specify specific columns to query as you have done here:

places = db.session.query(Place.roll_number, Place.name,
    Place.website, Place.address, Place.distance).\
    outerjoin(Rank, Rank.place_id == Place.place_id)

the result is expressed as a collection of tuples.

My first impression was that can't set attribute was a strange error message to receive from trying to assign an attribute value to a tuple, so I tried it:

>>> t = tuple()
>>> t.attribute = 9
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple'object has no attribute 'attribute'

That's not the error message that you received.

So I performed a query similar to your second one (the model is just something from a project that I had open):

>>>q = session.query(Racecard.id, Racecard.meeting)>>>a_result = q[0]>>>type(a_result)
<class 'sqlalchemy.util._collections.result'>

Right, so we aren't getting a tuple, we get a sqlalchemy.util._collections.result object. But..

>>> issubclass(type(a_result), tuple)
True

So, the sqlalchemy.util._collections.resultis a type of tuple.

If we try to assign a value to an attribute that is not one of the columns that were queried:

>>> a_result.newattribute ='something'
Traceback (most recent calllast):
  File "<stdin>", line 1, in<module>
AttributeError: 'result' object has no attribute 'newattribute'

That error message is very similar to the one that we got before when assigning an attribute to a plain tuple.

So why did you get a different error message? The result object is actually more like a namedtuple:

>>>from collections import namedtuple>>>Racecard = namedtuple('Racecard', 'id, meeting')>>>rc = Racecard(1, 'Doomben')>>>rc.meeting = 'Eagle Farm'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

Which is the same error message that you are getting.

So, the sqlalchemy.util._collections.result object supports attribute access of the column names, but as it is a tuple it is still immutable, so you cannot write to those attributes.

To fix your specific error (unless there was some reason that you were specifically querying only those columns) change your places query to:

places = db.session.query(Place).outerjoin(Rank, Rank.place_id == Place.place_id)

Solution 2:

Another possible cause for this error ("AttributeError: can't set attribute" error) is when you have both a column and a property with an identical name.

It happened to me with an @property that I had previously added (and forgotten about), then created a column with the same name.

Post a Comment for "Can't Set Attribute On Result Objects In Sqlalchemy Flask"