AttributeError while querying: Neither 'InstrumentedAttribute' object nor 'Comparator' has an attribute

50,273

Solution 1

This is because you are trying to access bar from the FooBar class rather than a FooBar instance. The FooBar class does not have any bar objects associated with it--bar is just an sqlalchemy InstrumentedAttribute. This is why you get the error:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with FooBar.bar has an attribute 'foo'

You will get the same error by typing FooBar.bar.foo.name outside the sqlalchemy query.

The solution is to call the Foo class directly:

ses.query(FooBar).join(Bar).join(Foo).filter(Foo.name == "blah")

Solution 2

I cannot explain technically what happens but you can work around this problem by using:

ses.query(FooBar).join(Foobar.bar).join(Bar.foo).filter(Foo.name == "blah")

Solution 3

I was getting the same error Neither 'InstrumentedAttribute' object nor 'Comparator' has an attribute, but in my case, the problem was my model contained a Column named query, which was overwriting the internal property model.query.

I decided to rename that Column to query_text and that removed the error. Alternatively, passing the name= argument to the Column method would have worked: query = db.Column(db.TEXT, name='query_text').

Solution 4

A related error that can be caused by configuring your SQLAlchemy relationships incorrectly:

AttributeError: Neither 'Column' object nor 'Comparator' object has an attribute 'corresponding_column'

In my case, I incorrectly defined a relationship like this:

namespace   = relationship(PgNamespace, id_namespace, backref="classes")

The id_namespace argument to relationship() should just not be there at all. SQLAlchemy is trying to interpret it as an argument of a different type, and failing with an inscrutable error.

Share:
50,273
Bleeding Fingers
Author by

Bleeding Fingers

SSBsb3ZlIHByb2JsZW0tc29sdmluZywgcHJvZ3JhbW1pbmcsIGFuZCByZWFkaW5nIGFuZCBsZWFy\nbmluZyBhbG1vc3QgYW55dGhpbmcgcmVsYXRlZCB0byB0aGUgZmllbGQgb2YgY29tcHV0ZXJzIGlu\nIG15IHNwYXJlIHRpbWUuIEJSQiB3aXRoIG1vcmUu\n I am nerdier than 87% of all people. Are you a nerd? Click here to take the Nerd Test, get geeky images and jokes, and write on the nerd forum! http://www.nerdtests.com/images/ft/nq/9ffc03eb9d.gif

Updated on November 21, 2020

Comments

  • Bleeding Fingers
    Bleeding Fingers over 3 years

    The following code:

    Base = declarative_base()
    engine = create_engine(r"sqlite:///" + r"d:\foo.db",
                           listeners=[ForeignKeysListener()])
    Session = sessionmaker(bind = engine)
    ses = Session()
    
    class Foo(Base):
        __tablename__ = "foo"
        id = Column(Integer, primary_key=True)
        name = Column(String, unique = True)
    
    class Bar(Base):
        __tablename__ = "bar"
        id = Column(Integer, primary_key = True)
        foo_id = Column(Integer, ForeignKey("foo.id"))
    
        foo = relationship("Foo")
    
    
    class FooBar(Base):
        __tablename__ = "foobar"
        id = Column(Integer, primary_key = True)
        bar_id = Column(Integer, ForeignKey("bar.id"))
    
        bar = relationship("Bar")
    
    
    
    Base.metadata.create_all(engine)
    ses.query(FooBar).filter(FooBar.bar.foo.name == "blah")
    

    is giving me this error:

    AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with FooBar.bar has an attribute 'foo'
    

    Any explanations, as to why this is happening, and guidance to how such a thing could be achieved?

  • Flamínio Maranhão
    Flamínio Maranhão over 9 years
    You can understand why it works in the documentation: docs.sqlalchemy.org/en/rel_0_9/orm/…
  • rr-
    rr- almost 8 years
    What if the table has multiple relations to Foo?
  • Jim Hunziker
    Jim Hunziker over 5 years
    This is correct, and the accepted answer is wrong because it does not join the tables on their foreign keys. You can actually remove the .bar and the .foo from this answer, and it still works.
  • gatherer
    gatherer over 4 years
    Thank you! A column and a relationship having the same name was causing this error and I didn't spot it until reading this answer.
  • Ricky Levi
    Ricky Levi almost 2 years
    That's true, but then we need to run .join() in every query of the app ( i.e: user id allowed/not allowed) - in that case, how can i "save" all these "join"s ?