Seite 1 von 1

Flask-SQLAlchemy query.filter_by()

Verfasst: Freitag 26. März 2021, 11:03
von naheliegend
Hi,

ich möchte alle Trainings haben bei denen gilt Slot.taken==True.

Wieso kann ich das nicht folgendermaßen abfragen und erhalte eine Fehlermeldung?

Code: Alles auswählen


class Training(db.Model):
    __tablename__ = 'trainings'
    id = db.Column(db.Integer, primary_key=True, index=True)
    (...)
    #relationships
    slot_id = db.Column(db.Integer, db.ForeignKey('slots.id')) #foreign key to the table name


class Slot(db.Model):
    __tablename__ = 'slots'
    id = db.Column(db.Integer, primary_key=True, index=True)
    (...)
    taken = db.Column(db.Boolean(), index=True)
    #relationships
    trainings = db.relationship('Training', backref='slots', uselist=False)


example = Training.query.filter_by(Training.slots.taken==True).first()


Fehler:

Code: Alles auswählen

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Training.slots has an attribute 'taken'

Re: Flask-SQLAlchemy query.filter_by()

Verfasst: Freitag 26. März 2021, 12:27
von naheliegend

Code: Alles auswählen

example = Training.query.join(Slot).filter_by(taken=True).first()
Funktioniert auch nicht....

Code: Alles auswählen

sqlalchemy.exc.InvalidRequestError: Entity namespace for "trainings" has no property "taken"

Re: Flask-SQLAlchemy query.filter_by()

Verfasst: Freitag 26. März 2021, 15:39
von naheliegend
So funktioniert es:

Code: Alles auswählen

example = Training.query.join(Slot).filter(Slot.taken==True).first()
Intuitiv finde ich das aber nicht... da kann man ja fast besser sql schreiben.

Re: Flask-SQLAlchemy query.filter_by()

Verfasst: Freitag 26. März 2021, 18:38
von __blackjack__
@naheliegend: Es muss halt eindeutig sein. Wenn Du nicht sagst, dass das `taken` von `Slot` kommt muss man raten wo es her kommt und falls dann irgendwann `Training` auch mal ein `taken` bekommen sollte, dann geht das nicht mehr, oder bedeutet eventuell was anderes.

Das `join()` müsste man weglassen können, denn das ist implizit klar wenn in der Bedingung eine weitere Tabelle vorkommt.

Re: Flask-SQLAlchemy query.filter_by()

Verfasst: Freitag 26. März 2021, 20:16
von naheliegend
__blackjack__ hat geschrieben: Freitag 26. März 2021, 18:38 (...)

Das `join()` müsste man weglassen können, denn das ist implizit klar wenn in der Bedingung eine weitere Tabelle vorkommt.
Bekomme ohne join() eine Warnung:

Code: Alles auswählen

SAWarning: SELECT statement has a cartesian product between FROM element(s) "slots" and FROM element "trainings".  Apply join condition(s) between each element to resolve.
Und für bestimmte andere Queries bekomme ich auch verschiedene Ergebnisse...

Re: Flask-SQLAlchemy query.filter_by()

Verfasst: Dienstag 27. April 2021, 10:33
von strassi
Ohne es genau getestet zu haben und zwischen "Tür und Angel" würde ich folgendes vermuten:
Ändere mal die Referenz (slots), da du die Tabelle ja auch den Namen (slots) hat und er sich hier ggf. verhaspelt.... Ich hatte mit der Referenz und Tabellennamen auch schon die ein oder andere Schwierigkeit...

Code: Alles auswählen

class Slot(db.Model):
    __tablename__ = 'slots'
    id = db.Column(db.Integer, primary_key=True, index=True)
    (...)
    taken = db.Column(db.Boolean(), index=True)
    #relationships
    trainings = db.relationship('Training', backref='plaetze', uselist=False)
Generell bin ich bei __blackjack__ -> das join() brauchst du eigentlich nicht.