How to create a SQL query with optional parameters in Python Flask? How to create a SQL query with optional parameters in Python Flask? flask flask

How to create a SQL query with optional parameters in Python Flask?


I prefer to use Python's format string function for this. It's splitting hairs, but format allows to set name in the string, so it's technically more explicit. However, I would suggest using **kwargs instead of *args, so you don't have to rely on magic.

UPADATE 2019

This was a terrible answer. You never, ever, EVER want to take user generated data and interpolate it directly into a SQL query. It is imperative that you always sanitize user input in order to protect against SQL injection. Python has defined a database API specification that any database package that is not an ORM like SQLAlchemy should implement. Long story short, you should be NEVER, EVER, EVER use str.format(), %, or "fstrings" to interpolate data into your SQL queries.

The database API specification provides a way to safely interpolate data into queries. Every python database interface should have a Cursor class that is returned from a Connection object. The Cursor class will implement a method named execute. This obviously will execute a query, but it will also have a second argument–usually called args. According to the specification:

Parameters may be provided as sequence or mapping and will be bound to variables in the operation. Variables are specified in a database-specific notation (see the module's paramstyle attribute for details).

By "sequence", it means that args can be a list or tuple, and by "mapping", it means that args can also be a dict. Depending on the package, the way to specify where your data should be interpolated may differ. There are six options for this. Which formatting the package you're using can be found in the paramstyle constant of the package. For instance, PyMySQL(and most implementations of the spec that I've used) uses format and pyformat. A simple example would be:

format

cursor.execute('SELECT * FROM t WHERE a = %s, b = %s;', (1, 'baz'))

pyformat

cursor.execute('SELECT * FROM t WHERE a = %(foo)s, b = %(bar)s;', {'foo': 1, 'bar': 'baz'})

Both of these would execute as:

SELECT * FROM t WHERE a = 1, b = 'baz';

You should make sure to explore the documentation of the database API package you're using. One extremely helpful thing I came across using psycopg2, a PostgresSQL package, was its extras module. For instance, a common problem when trying to insert data securely is encountered when inserting multiple rows at once. psycopg2 has a clever solution to this problem in its execute_values function. Using execute_values, this code:

execute_values(cursor, "INSERT INTO t (a, b) VALUES %s;", ((1, 'foo'), (2, 'baz')))

... is executed as:

"INSERT INTO t (a, b) VALUES (1, 'foo'), (2, 'baz');"