TypeError: 'dict' object does not support indexing thrown on second instance of this query

前端 未结 1 825
醉梦人生
醉梦人生 2021-01-19 02:47

So I am building a query based on user input in flask with this code:

    if empty_indic_form.validate_on_submit():
    query=\'select name, year, value, dis         


        
相关标签:
1条回答
  • 2021-01-19 03:27

    The fundamental error in your method is using string concatenation to build an SQL query. If indic_form.indicators.data or order_c is user provided data, for example from an HTTP request, you've probably opened yourself up for SQL injection. The error

    TypeError: 'dict' object does not support indexing
    

    is the result of this concatenation: your query string contains a rogue "%", which is part of the placeholder syntax of psycopg – the DB-API usually used with SQLAlchemy to talk to Postgresql. This is exactly the reason why manual concatenation should not be done. Getting escaping right can be hard.

    Passing a list of values to IN operator is done using tuples adaptation in Psycopg2. In SQLAlchemy you'd use the in_ column operator, or an expanding bind param that were introduced in version 1.2.

    Unfortunately in your particular case the SQLAlchemy wrapping, the engine, has a gotcha: as all your arguments would be tuples, the SQLAlchemy engine thinks that you're trying to pass it an iterable of argument tuples as multiparams and uses executemany() automatically. You can work around this by using the text() construct, which allows for DB-API agnostic bound parameter syntax and dictionaries as argument containers:

    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()
    

    To recap: never build SQL queries using string concatenation or manual formatting. Always use placeholders / bound parameters.

    0 讨论(0)
提交回复
热议问题