4

I have bunch of complicated sql queries that I need to execute on Django and Raw SQL seems to be the only option. My parameters are strings and can be empty. The reason for being empty is that I have conditional statements above, and depending on that the correct sql needs to be executed. But when the ra sql is run, django actually puts quotes (which I use to denote strings) in the sql and so it throws an error.

I have simplified the query to show the problem I am facing. The following query when executed throws an error.

select_cond = ''
where_cond = 'id = 109'

qraw = Book.objects.raw(
        "\
        SELECT  id %s\
        FROM book\
        WHERE %s\
        ",
        [select_cond, where_cond]
)

The error is due to it being translated as follows. The quotes actually get in the sql and so it won't execute. Any idea on how I can fix this?

 SELECT  id ''
 FROM book
 WHERE 'id = 109'
 ORDER BY id DESC;

2 Answers 2

4

Django provides a 'params' argument for raw that avoids the potential for SQL injection attacks. As @alecxe's example shows, triple quotes in python are a great way to define a multi-line variable and avoid any backslash line escapes. Here's a proposed safe solution the "Django way":

select_cond = condition
where_cond = condition

qraw = Book.objects.raw("""
    SELECT
        id, %(select_cond)s
    FROM
        book
    WHERE
        %(where_cond)s
    """, params={'select_cond': select_cond, 'where_cond': where_cond})

Just replace condition placeholders with appropriate values.

Sign up to request clarification or add additional context in comments.

Comments

3

This is the default behavior of the underlying database driver used by Django.

Note: I'm not sure the motivation behind trying to construct the query this way.

Only if you trust the source of the where conditions you are using in the queries, put them into the query via string formatting:

qraw = Book.objects.raw("""
    SELECT 
        id, {select}
    FROM 
        book
    WHERE 
        {where}
    """.format(select=select_cond, where=where_cond)
)

Again, this is not safe to do since you are actually making it vulnerable to SQL injections.


To make it safer you can pre-parse the where conditions you'll be using in the query and call MySQLdb.escape_string() manually on the field values, example:

key, value = where_cond.split(' = ')
value = MySQLdb.escape_string(value)
where_cond = ' = '.join(key, value)

1 Comment

I guess noting about it being not safe 3 times is not enough to avoid downvotes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.