django query get last n records

Django

Django 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)]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames LinView Question on Stackoverflow
Solution 1 - DjangoRobert KajicView Answer on Stackoverflow
Solution 2 - DjangoOmid RahaView Answer on Stackoverflow
Solution 3 - DjangoALLSYEDView Answer on Stackoverflow
Solution 4 - DjangoComplex_ConjugateView Answer on Stackoverflow
Solution 5 - DjangoAndreas ChristofiView Answer on Stackoverflow
Solution 6 - DjangoTài HatranducView Answer on Stackoverflow