Ich habe zwei Tabellen table_a
und table_b
. table_b.code_b
ist der Fremdschlüssel der table_a
sqlalchemy needload Abfrage kann nicht zum Zählen
table_a
code_a, val
-----------
aaa,100
table_b
code_b, name
------------
aaa, name1
ich mit Verbinden von zwei Tabellen dieses Ergebnis erhalten möchten:
table_result
code_a,val,name
---------------
aaa,100,name1
Im Folgenden ist der Python-Code:
class A(db.Model):
__tablename__ = 'table_a'
code_a = Column(String(20), ForeignKey("table_b.code_b"), primary_key=True)
val = Column(Float)
b = relationship("B", backref=backref('table_b'))
class B(db.Model):
__tablename__ = 'table_b'
code_b = Column(String(20), primary_key=True)
name = Column(String(100))
a = relationship("A", backref="table_a")
where_str = "code_b='aaa'"
q = A.query.options(joinedload_all(A.b)).filter(text(where_str))
rows1 = [i.serialize for i in q.all()] # CORRECT
rows2 = [i.serialize for i in q.paginate(1,10,False)] # ERROR
Wenn ich nur alles abfragen, um rows1
zu erhalten, ist es korrektes Ergebnis. Allerdings werde ich Fehler erhalten mit fliessendem rows2
: Database: (cx_Oracle.DatabaseError) ORA-00904: "code_b"
ich diesen Fehler debuggen mit Druck die SQL-Anweisung:
SELECT count(*) AS count_1
FROM (SELECT "table_a".code_a AS "table_a_code_a",
FROM "table_a"
WHERE code_b = 'aaa') anon_1
Es ist klar, dass zwei Tabellen sind NICHT beigetreten.
Wenn aber nur q.all()
, wird SQL-Anweisung sein:
SELECT "table_a".code_a AS "table_a_code_a",
FROM "table_a" LEFT JOIN "table_b"
WHERE code_b = 'aaa'
Das ist richtig.
So, wie Sie das richtige Ergebnis beim Erstellen der Seitennummerierung erhalten.
EDIT1:
F: Warum ich where_str
verwenden?
A: In der HTML-Seite verwende ich den Abfrage-Generator (http://querybuilder.js.org/), Abfragefilter zu bekommen (vielleicht kompliziert). So ist es bequem, SQLAlchemy Query Filer zu übergeben.
Gibt es bessere Möglichkeiten, dies zu implementieren?
EDIT2: Lösung:
q = A.query.join(A.b).options(contains_eager(A.b)).filter(text(where_str))
Dank, sehen Sie bitte meine Frage Update :) – seizetheday
@seizetheday Nur weil Sie das passieren müssen Filter vom Frontend aus bedeutet nicht, dass Sie ein 'text' Konstrukt verwenden müssen. Unabhängig davon, dass Sie ein 'text' Konstrukt verwenden, ist das Problem nicht per se; Das Problem ist, dass Sie 'join' anstelle von' .join' verwenden. – univerio
Danke, Lebensretter! – seizetheday