Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django filter multiple columns with a list of tuples

I have a simple model with 2 fields:

class Simple(Model)
    class Meta:
        index_together = True

    a = IntField()
    b = IntField()

I would like to generate an SQL query for tuples of values for a,b. e.g.

select * 
from SimpleModel 
where (a,b) in ((1,1), (4,8), ...)

I know how to create something like:

select * 
from SimpleModel 
where ((a = 1 and b = 1) or (a = 4 and b = 8))

Which is logically the same, but I think my DB has a problem when the number of possible values is very big (I am using Postgresql), also the query itself is much longer so it's heavier on the network, and probably harder for it to analyze and read it correctly (i.e. use the composite index in this case).

So, the question is, can I get Django to create the query in the first form?

Thanks!

like image 344
idanzalz Avatar asked Jun 02 '14 09:06

idanzalz


1 Answers

@Wolph answer is correct but I would do it this way

tuple_of_tuples = ((1,1), (4,8))
Simple.objects.extra(where=['(a,b) in %s'], params=[tuple_of_tuples])

Check here about passing a tuple and not a list

Passing lists or tuples as arguments in django raw sql

For the params I quote from Django docs https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.extra

params

The where parameter described above may use standard Python database string placeholders — '%s' to indicate parameters the database engine should automatically quote. The params argument is a list of any extra parameters to be substituted.

Example:

Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

Always use params instead of embedding values directly into where because params will ensure values are quoted correctly according to your particular backend. For example, quotes will be escaped correctly.

like image 58
Nour Wolf Avatar answered Sep 18 '22 17:09

Nour Wolf