Wie ein automatischen Filter auf eine Beziehung mit SQLAlchemy hinzufügen?
-
06-07-2019 - |
Frage
Ich verwende SQLAlchemy 0.5rc, und ich möchte einen automatischen Filter auf eine Beziehung hinzuzufügen, so dass jedes Mal, er versucht, für diese Beziehung Aufzeichnungen zu holen, es ignoriert die „remote“ aus, wenn sie markiert sind als "logically_deleted" (ein boolean Feld der untergeordneten Tabelle)
Zum Beispiel, wenn ein Objekt „Eltern“ hat eine „Kinder“ Beziehung, die hat
3 Datensätze, aber einer von ihnen ist logisch gelöscht, wenn ich für „Parent“ abfragen, ich möchte SQLA zu
holt das übergeordnete Objekt mit nur zwei Kindern ..
Wie soll ich es tun? Durch das Hinzufügen eines „und“ Zustand der primaryjoin
Parameter der Beziehung? (Zum Beispiel „Children.parent_id == Parent.id and Children.logically_deleted == False
“, aber ist es richtig zu schreiben „und“ auf diese Weise?)
Bearbeiten
Ich schaffte es auf diese Weise tun
children = relation("Children", primaryjoin=and_(id == Children.parent_id, Children.logically_deleted==False))
aber ist es eine Möglichkeit, eine Zeichenfolge als primaryjoin stattdessen zu verwenden?
Lösung
Die and_ () Funktion ist der richtige Weg logische Konjunktionen in SQLAlchemy zu tun, zusammen mit dem Operator &, aber mit diesem vorsichtig sein, da es überraschend, Vorrangregeln hat, das heißt höhere Priorität als Vergleichsoperator.
Sie auch eine Zeichenfolge als eine primäre verbinden mit dem Text () Konstruktor verwenden könnte, aber das wird Ihren Code Bruch mit jedem Tisch Aliasing, die mit eagerloading und verbindet kommt machen.
Für logisches Löschen, könnte es besser sein, die ganze Klasse über eine ausgewählte abzubilden, die Werte gelöscht ignoriert:
mapper(Something, select([sometable], sometable.c.deleted == False))
Andere Tipps
aber ist es eine Möglichkeit, eine Zeichenfolge als primaryjoin stattdessen zu verwenden?
Sie können das folgende:
children = relationship("Children", primaryjoin="and_(Parent.id==Children.parent_id, Children.logically_deleted==False)"
Das funktioniert für mich!
Ich bin nur zur Zeit der Entwicklung agains 0.4.something, aber hier ist, wie ich es vorschlagen würde:
db.query(Object).filter(Object.first==value).filter(Object.second==False).all()
Ich denke, das ist, was Sie zu tun versuchen, nicht wahr?
(Hinweis: in einem Web-Browser geschrieben, nicht echter Code)