Django - limiting query results

Viewed 244945

I want to take the last 10 instances of a model and have this code:

 Model.objects.all().order_by('-id')[:10]

Is it true that firstly pick up all instances, and then take only 10 last ones? Is there any more effective method?

7 Answers

Slicing of QuerySets returns a list which means if you do like:

>>> Model.objects.all().order_by('-id')[:10]

it will return a list and the problem with that is you cannot perform further QuerySet methods on list

So if you want to do more on the returned results, you can:

>>> limit = 5 # your choice
>>>
>>> m1 = Model.objects.filter(pk__gte=Model.objects.count() - limit) # last five
>>> m2 = Model.objects.filter(pk__lte=limit)  # first five

Now you can perform more methods:

# Just for illustration
>>> m2.annotate(Avg("some_integer_column")) # annotate
>>> m2.annotate(Sum("some_integer_column"))
>>> m2.aggregate(Sum("some_integer_column")) # aggregate

By using slice notation([]) to limit results, you may also limit the ability to chain QuerySet methods.

If you are pretty sure that you will not need to make any further query then slicing will do the thing.

The simple answer for filter issue

Notification.objects.filter(user=request.user).order_by("-id")[:limit]

Just put order_by and then [:limit]

As an addition and observation to the other useful answers, it's worth noticing that actually doing [:10] as slicing will return the first 10 elements of the list, not the last 10...

To get the last 10 you should do [-10:] instead (see here). This will help you avoid using order_by('-id') with the - to reverse the elements.

Related