2016-06-29 25 views
3

ich eine Abfrage mit diesem Code auf Basis von Benutzereingaben in der Flasche am Aufbau So geworfen nicht unterstützt:Typeerror: ‚dict‘ Objekt Indizierung auf der zweiten Instanz dieser Abfrage

if empty_indic_form.validate_on_submit(): 
    query='select name, year, value, display_name from literal inner join ent on ent_id=ent.id where display_name in (' 
    for i in indic_form.indicators.data: 
     query=query+'\''+i+'\',' 
    query=query[:-1]+') ' 
    query=query+'and name in (' 
    for c in order_c: 
     query=query+c+',' 
    query=query[:-1]+')' 
    data_return=db.engine.execute(query).fetchall() 

Ich habe bestätigt, dass Abfrage aussieht was es soll, und hatte sogar eine frühere Sitzung, wo es eine Liste von rowproxy-Objekten zurückgab, wie ich es erwartet hatte. Aber ich bekomme diesen Fehler nicht, egal was ich mache!

ich Abfrage auf eine Variable in den Vorlagen festgelegt haben, damit ich es ausdrucken können, und hier ist das, was ich bekommen:

select name, year, value, display_name from literal inner join ent on ent_id=ent.id where display_name in ('Energy savings of primary energy (TJ)','Adolescent birth rate (women aged 15-19 years)','Net migration rate','Transmission and distribution losses (%)') and name in ('Burkina Faso', 'Ghana', 'Saudi Arabia', 'Pakistan')

lief ich, dass direkt auf meine Postgres DB und das Ergebnis war großartig.

In der Fehler-Dump merke ich, dass die data_return=db.engine.execute(query).fetchall() Zeile mit einem leeren Wörterbuch als die Parameter erstellt, die natürlich diesen Fehler am Ende wirft. Kann ich es zwingen, dies nicht zu tun? Das Abfrageobjekt sieht wie oben aus, was ist jetzt falsch? Sollte ich die db-Sitzung möglicherweise beim Aktualisieren der Seite oder auf der Startseite beenden?

+0

am db.engine.execute Stack-Trace Linie Dumping ich '' "query = \t u'select Name, Jahr, den Wert, display_name von wörtlicher Exklusionsverknüpfung ent auf ent_id = ent.id wo display_name in ("Altersabhängigkeitsquote, 65 Jahre und älter", "Waldfläche (% der gesamten Landfläche)", "Energieintensität des Verkehrssektors (MJ/2011 USD PPP)", "Divisia Zerlegungsanalyse - Energieintensitätskomponentenindex" "," HDI: Durchschnittliche jährliche Wachstumsrate, 2000-2013 "," GDI: Erwartete Schuljahre, Männer ") und in (" Saudi-Arabien "," Pakistan "," Finnland "," Jamaika ")" "genannt so Ill versuchen, von Unicode zu str zu zwingen? –

+0

Nicht wirklich vertraut, aber für psycopg2 verwendet die normale Abfrage dreifach zitierte Literale. Hast du das probiert? – Wboy

+0

Wo die vollständige Traceback-Nachricht? –

Antwort

7

Der grundlegende Fehler in Ihrer Methode besteht in der Verwendung von String-Verkettung zum Erstellen einer SQL-Abfrage. Wenn oder order_c vom Benutzer zur Verfügung gestellte Daten sind, zum Beispiel von einer HTTP-Anfrage, haben Sie sich wahrscheinlich für SQL injection geöffnet. Der Fehler

TypeError: 'dict' object does not support indexing 

ist das Ergebnis dieser Verkettung: Ihre Abfrage-Zeichenfolge enthält ein Schelm "%", die einen Teil der Platzhalter-Syntax von psycopg ist - der DB-API in der Regel verwendet, um mit SQLAlchemy zu Postgresql zu sprechen. Dies ist genau der Grund, warum manuelle Verkettung nicht durchgeführt werden sollte. Es kann schwierig sein, richtig zu entkommen.

Die Übergabe einer Werteliste an den Operator IN erfolgt mit tuples adaptation in psycopg. In SQLAlchemy würden Sie den Spaltenoperator in_ verwenden, aber ich weiß nicht, wie man ihn (oder eine andere Methode) mit manuellen SQL-Abfragezeichenfolgen verwendet.

Leider gibt es in Ihrem speziellen Fall die SQLAlchemy Verpackung, der Motor hat eine Gotcha: wie alle Ihre Argumente Tupel wäre, die SQLAlchemy Motor denkt, dass Sie versuchen, es als multiparams ein iterable Argumentations Tupel übergeben und verwendet executemany() automatisch. Sie können mithilfe des text() Konstrukt dieses Problem umgehen, die für die DB-API Agnostiker verknüpfter Parameter Syntax und Wörterbücher als Argument Container erlaubt:

from sqlalchemy import text 

... 

if empty_indic_form.validate_on_submit(): 
    # Note that the placeholders shouldn't have enclosing parentheses 
    query = """SELECT name, year, value, display_name 
       FROM literal 
       INNER JOIN ent ON ent_id = ent.id 
       WHERE display_name IN :display_name 
       AND name IN :name""" 

    data_return = db.engine.execute(
     text(query), {'display_name': tuple(indic_form.indicators.data), 
         'name': tuple(order_c)}).fetchall() 

Zur Erinnerung: nie Formatierung mit String-Verkettung oder manuelle SQL-Abfragen erstellen. Verwenden Sie immer Platzhalter/gebundene Parameter.

+0

das ist fantastisch, danke! Ich habe Schwierigkeiten, die Dokumentation von Sql Alchemy zu navgagen, wo kann ich mehr über Platzhalter/Grenzen sehen? –

+0

Ich bekomme auch jetzt diese 'Datei" C: \ Benutzer \ Vince \ Google Drive \ PeacefulMandE \ Vasco de Daten \ Vasco \ views.py ", Zeile 66, in show_avail {'display_name': tuple (indic_form.indicators .data), TypeError: Objekt 'NoneType' ist nicht iterierbar ' –

+0

Prolly 'indic_form.indicators.data' ist' None'. Behandeln Sie diesen Spezialfall einfach so, wie es Ihnen am besten passt. Für weitere Informationen über die Verwendung von SQL-Text mit SQLAlchemy, lesen Sie http://docs.sqlalchemy.org/en/latest/core/tutorial.html#using-textual-sql –