How can I sort a column in Django admin by some simple custom method?
(All the answers I got through was by using annotate
but I don't know how to use it my case).
Assume the model
class Shots(models.Model):
hits = models.PositiveIntegerField()
all = models.PositiveIntegerField()
In admin site I would like to sort by hits to all
ratio:
class ShotAdmin(admin.ModelAdmin):
list_display = ['ratio']
def ratio(self, obj):
return obj.hits / obj.all * 100
I know the ratio
is not a field in DB thus simple ratio.admin_order_field = 'ratio'
won't work and I need to somehow append this as a field but I have no idea how.
How to set ordering of Apps and models in Django admin dashboard. ¶ Django, by default, orders the models in admin alphabetically. So the order of models in Event admin is Epic, EventHero, EventVillain, Event Instead you want the order to be EventHero, EventVillain, Epic then event.
However, if an element of list_display represents a certain database field, you can indicate this fact by using the display () decorator on the method, passing the ordering argument: The above will tell Django to order by the first_name field when trying to sort by colored_first_name in the admin.
Watch it together with the written tutorial to deepen your understanding: Django Admin Customization The Django framework comes with a powerful administrative tool called admin. You can use it out of the box to quickly add, delete, or edit any database model from a web interface.
Adding the ordering attribute will default all queries on Person to be ordered by last_name then first_name. Django will respect this default order both in the admin and when fetching objects. The list_display tuple can reference any attribute of the object being listed.
By following:
We can compose a solution to your problem:
from django.db.models import F
class ShotsAdmin(admin.ModelAdmin):
list_display = ('get_ratio',)
def get_queryset(self, request):
qs = super(ShotsAdmin, self).get_queryset(request)
qs = qs.annotate(ratio=F('hits') * 100 / F('all'))
return qs
def get_ratio(self, obj):
return obj.ratio
get_ratio.admin_order_field = 'ratio'
Explanation:
get_queryset
method will annotate a new field named ratio
to
your queryset. That field's value is the application of your ratio function on the hits
and all
fields.get_ratio
function returns the aforementioned field from a queryset instance.get_ratio.admin_order_field = 'ratio'
sets the ratio
field as the ordering field for your queryset on the admin panel.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With