web-dev-qa-db-fra.com

AttributeError lors d'une requête: ni l'objet 'InstrumentedAttribute' ni le 'comparateur' n'ont d'attribut

Le code suivant:

Base = declarative_base()
engine = create_engine(r"sqlite:///" + r"d:\foo.db",
                       listeners=[ForeignKeysListener()])
Session = sessionmaker(bind = engine)
ses = Session()

class Foo(Base):
    __table= "foo"
    id = Column(Integer, primary_key=True)
    name = Column(String, unique = True)

class Bar(Base):
    __table= "bar"
    id = Column(Integer, primary_key = True)
    foo_id = Column(Integer, ForeignKey("foo.id"))

    foo = relationship("Foo")


class FooBar(Base):
    __table= "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")

me donne cette erreur:

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

Des explications, pourquoi cela se produit-il, et des indications sur la manière dont une telle chose pourrait être réalisée?

30
Bleeding Fingers

En effet, vous essayez d'accéder à bar à partir de la classe FooBar plutôt qu'à une instance FooBar. La classe FooBar n'est associée à aucun objet bar --bar est simplement un sqlalchemy InstrumentedAttribute . C'est pourquoi vous obtenez l'erreur:

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

Vous obtiendrez la même erreur en tapant FooBar.bar.foo.name en dehors de la requête sqlalchemy.

La solution consiste à appeler directement la classe Foo:

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

Je ne peux pas expliquer techniquement ce qui se passe, mais vous pouvez contourner ce problème en utilisant:

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

Je recevais la même erreur Neither 'InstrumentedAttribute' object nor 'Comparator' has an attribute, mais dans mon cas, le problème était que mon modèle contenait une colonne nommée query, qui remplaçait la propriété interne model.query.

J'ai décidé de renommer cette colonne en query_text et cela a supprimé l'erreur. Sinon, passer l'argument name= à la méthode Column aurait fonctionné: query = db.Column(db.TEXT, name='query_text').

0
tokenizer_fsj

Une erreur connexe pouvant être provoquée par une configuration incorrecte de vos relations SQLAlchemy:

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

Dans mon cas, j'ai mal défini une relation comme celle-ci:

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

L'argument id_namespace à relationship() ne devrait tout simplement pas être là. SQLAlchemy tente de l'interpréter comme un argument d'un type différent et échoue avec une erreur impénétrable.

0
qris