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?
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?
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.