Question

I am wondering when I touch db when doing queries. more precisely, when is the query performed:

i have this kwargs dic:

kwargs = {'name__startswith':'somename','color__iexact':'somecolor'}

but only for name__startswith query, i need to distinct(). and not for color__iexact.

I thought, i would set for name__startswith the distinct() in loop like this:

for q in kwargs: 
  if q == 'name__startswith':
    Thing.objects.filter(name__startswith=somename).distinct('id')

and then query for all dynamically:

allthings = Thing.objects.filter(**kwargs)

but this is somehow wrong, i seem to be doing two different things here..

how can i do these two queries dynamically?

Was it helpful?

Solution

django querysets are lazy, so the actual queries aren't evaluated until you use the data.

allthings = Thing.objects.filter(**kwargs)

if 'name__startswith' in kwargs:
  allthings = allthings.distinct('id')   

No queries should be preformed above unitl you actually use the data. This is great for filtering queries as you wish to do


From the docs:

QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated. Take a look at this example:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

Though this looks like three database hits, in fact it hits the database only once, at the last line (print(q)). In general, the results of a QuerySet aren’t fetched from the database until you “ask” for them. When you do, the QuerySet is evaluated by accessing the database. For more details on exactly when evaluation takes place, see When QuerySets are evaluated.

OTHER TIPS

You can use models.Q to create dynamic queries in django.

query = models.Q(name__startswith=somename)

query &= models.Q('color__iexact':'somecolor')

all_things = Thing.objects.filter(query).distinct('name')

Also read Constructing Django filter queries dynamically with args and kwargs

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top