2008-11-06 14 views
8

Ich benutze SQLAlchemy 0.5rc, und ich möchte einen automatischen Filter zu einer Beziehung hinzufügen, so dass jedes Mal, wenn es versucht, Datensätze für diese Beziehung abzurufen, die "Remote" ignoriert, wenn sie als markiert sind "logically_deleted" (ein boolesches Feld der Kindtabelle)Wie fügt man einer Beziehung mit SQLAlchemy einen automatischen Filter hinzu?

Zum Beispiel, wenn ein Objekt "Eltern" hat eine "Kinder" Beziehung, die 3 Datensätze hat, aber einer von ihnen ist logisch gelöscht, wenn ich für " Parent "Ich möchte SQLA zu holen das übergeordnete Objekt mit nur zwei Kindern.
Wie soll ich es tun? Durch Hinzufügen einer "und" -Bedingung zum primären Parameter der Beziehung? (ZB „Children.parent_id == Parent.id and Children.logically_deleted == False“, aber ist es richtig zu schreiben „und“ auf diese Weise?)

Edit:
Ich schaffte es auf diese Weise zu tun

children = relation("Children", primaryjoin=and_(id == Children.parent_id, Children.logically_deleted==False)) 

aber ist es eine Möglichkeit, stattdessen eine Zeichenfolge als primaryjoin verwenden?

Antwort

3

Die and_() Funktion ist der richtige Weg logische Konjunktionen in SQLAlchemy zu tun, zusammen mit dem & Operator, aber mit diesem vorsichtig sein Es hat überraschende Vorrangregeln, dh höhere Priorität als Vergleichsoperatoren.

Sie können auch eine Zeichenfolge als primären Join mit dem text() -Konstruktor verwenden, aber dadurch wird Ihr Code mit jedem Tabellen-Aliasing, der mit equilerloading und Joins ausgeliefert wird, unterbrochen.

Für logisches Löschen, könnte es besser sein, die ganze Klasse über eine ausgewählte abzubilden, die gelöschten Werte ignoriert:

mapper(Something, select([sometable], sometable.c.deleted == False)) 
+0

Kann dies mit dem __mapper_args__ übersetzt werden? Ich meine, ich benutze deklarative. – Marconi

+0

Ich habe versucht, es in mapper_args zu verwenden, aber ich bekomme eine Fehlermeldung, dass "mapper() mehrere Werte für das Schlüsselwortargument 'local_table'" erhalten hat. Ich fürchte, es ist nutzlos. –

0

Ich bin derzeit nur agains 0.4.something, aber hier ist die Entwicklung, wie ich es würde vorschlagen:

db.query(Object).filter(Object.first==value).filter(Object.second==False).all() 

Ich denke, das ist, was Sie, richtig zu tun versuchen?

(Anmerkung: in einem Web-Browser geschrieben, nicht echten Code!)

+0

Nein, ich war auf der Suche nach etwas automatisch .. Ich werde die Frage klären :) Danke, aber! – Joril

+0

Keine Sorgen. Ich denke, ich verstehe, was Sie zu tun versuchen, aber vor allem lesen Sie den Code, den Sie zur Verfügung gestellt! –

6

aber ist es eine Möglichkeit, einen String zu verwenden, wie stattdessen primaryjoin?

Sie können die folgenden Befehle verwenden:

children = relationship("Children", primaryjoin="and_(Parent.id==Children.parent_id, Children.logically_deleted==False)" 

Dieser arbeitete für mich!