Problem
I wish to show only the last row of a QuerySet
based on the ModelAdmin
's ordering
criteria. I have tried a couple of methods, but none has worked for me.
Model:
class DefaultConfig(models.Model):
created_at = models.DateTimeField()
...
Attempt 1:
I tried overriding the ModelAdmin
's get_queryset
method and slicing super
's result, but I came up with some issues.
I.E:
class DefaultConfigAdmin(models.ModelAdmin):
model = Config
ordering = ('-created_at',)
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs[<slice>]
I tried the following values for [<slice>]
s:
[-1:]
: raised an Exception because negative slicing is not supported[:1]
: raisedAssertionError: Cannot reorder a query once a slice has been taken.
Attempt 2:
I tried obtaining the max value for created_at
and then filter
ing for records with that value. I.E:
class DefaultConfigAdmin(models.ModelAdmin):
model = Config
def get_queryset(self, request):
qs = super().get_queryset(request)
return qs.annotate(max_created_at=Max('created_at')).filter(created_at=F('max_created_at'))
But silly me, that works at row level, so it will only return aggregates over the row itself.
Further attempts (TBD):
Perhaps the answer lies in SubQuery
s or Window
ing and rank
ing.
Is there a more straight forward way to achieve this though?
CodePudding user response:
Did you try to set list_per_page = 1
?
class DefaultConfigAdmin(models.ModelAdmin):
model = Config
ordering = ('-created_at',)
list_per_page = 1
Technically this will still return all Config
objects, but only one per page and the latest one will be on the first page.
Another solution (similar to your "Attempt 2"), which involves an extra query, is to manually get hold of the latest created_at
timestamp and then use it for filtering.
class DefaultConfigAdmin(models.ModelAdmin):
model = Config
def get_queryset(self, request):
qs = super().get_queryset(request)
latest_config = qs.order_by('created_at').last()
return qs.filter(created_at=latest_config.created_at)