django query get last n records
DjangoDjango Problem Overview
Lets say I am implementing a message stream, records sort by ID ascending order, each fetch request, I want to only allow to fetch the most latest 10 records.
I tried:
Messages.objects.filter(since=since)[:-10]
And I had an error saying Negative Indexing is not supported.
My current work around is sort ID descending order, and then run:
Messages.objects.filter(since=since)[:10]
But this requires the front end to reverse the order again.
My question is, is there a elegant way to do it?
Django Solutions
Solution 1 - Django
You can pass your queryset to reversed:
last_ten = Messages.objects.filter(since=since).order_by('-id')[:10]
last_ten_in_ascending_order = reversed(last_ten)
Solution 2 - Django
Or use [::-1]
instead of reversed
:
last_ten = Messages.objects.filter(since=since).order_by('-id')[:10][::-1]
@ron_g:
> Above solution uses list comprehension twice (first to slice to 10, then to reverse). You can do it as one operation, it's 9x faster.
last_ten = Messages.objects.filter(since=since).order_by('-id')[:10:-1]
Solution 3 - Django
If you want last X records sorted in descending order by id , Then I don't think you need since filter
last_ten = Messages.objects.all().order_by('-id')[:10]
Using -id will sort in descending order. Hope this was helpful !!
Solution 4 - Django
I wanted to retrieve the last 25 messages and solved this problem in the following way
#models.py
class Meta:
ordering = ['created']
#views.py
message1 = []
for message in pm_messages.objects.filter(room=room_name).reverse()[0:25]:
message1.append(message)
messagess = message1.reverse()
Solution 5 - Django
In response to ron_g's comment in Omid Raha's answer:
Consider the case where there are less than 10 records in the list:
Note that this approach
list[:10:-1]
will return an empty list, in contrast to
list[:10][::-1]
which will return all the records in the list, if the total records are less than 10.
Solution 6 - Django
you can convert the queryset to a list and select the last n elements normally
messages = list(Messages.objects.filter(since=since))
messages = oldMessageis[-n:len(oldMessageis)]