Map (apply function) Django QuerySet

Viewed 12394

Is there a mechanism to map Django QuerySet items not triggering its evaluation?

I am wondering about something like Python map. A function that uses a function to apply it over the QuerySet, but keeping the lazy evaluation.

For example, using models from Django documentation example, is there something like? (not real code):

>>> Question.objects.all().map(lambda q: q.pub_date + timedelta(hours=1))

which keeps the lazy evaluation?

3 Answers

Just working through something like this myself. I think the best way to do it is to use a python list comprehension.

[q.pub_date + timedelta(hours=1) for q in Question.objects.all()]

Then Django takes care of optimizing this as it would any other query.

You can use annotate for this purpose, for example

from datetime import timedelta
from django.db.models import F, ExpressionWrapper, DateTimeField

Question.objects.annotate(
    new_pub_date=ExpressionWrapper(
       F('pub_date') + timedelta(hours=1), 
       output_field=DateTimeField()
    )
)

For something a little bit more complex than this example, you can use Func, Case, When

You can use values_list to get any column you like:

Question.objects.values_list('pub_date')

This is simpler than anything you can cook up yourself.

Related