1

how can I sort/order readonly_fields (see https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields)?

here is what I do:

class MyUserAdmin(UserAdmin):
    readonly_fields = ('pinCount')
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'is_active', 'date_joined', 'last_login', 'pinCount')

    def pinCount(self, instance):
        return Pin.objects.filter(user=instance).count()

admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)

In the admin it should be possible to sort the list by pinCount. Since it's not a direct database field, that's not possible according to the docs. Is there any way to do it?

Thanks!

2 Answers2

0

The ordering is done by the DB, not by the admin (this is debug toolbar output on a change list):

enter image description here

that's why you can't order by using a custom admin method. You could add a Count annotation to the admin's queryset by overwriting the ModeAdmin.queryset method:

class MyModelAdmin(admin.ModelAdmin):

    ...

    def queryset(self, request):
        qs = super(MyModelAdmin, self).queryset(request)
        return qs \
            .annotate(pin_count=Count('pin')) \
            .order_by('-pin_count')

or if you need more control, you could try sort the queryset displayed by the admin but I haven't tested this:

class MyModel(models.Model):
    ...

    @property
    def pin_count(self):
        return self.pin.count()


import operator  
class MyModelAdmin(admin.ModelAdmin):

    ...

    def queryset(self, request):
        qs = super(MyModelAdmin, self).queryset(request)
        return sorted(qs, key=operator.attrgetter('pin_count'))
Community
  • 1
  • 1
Timmy O'Mahony
  • 53,000
  • 18
  • 155
  • 177
0

I haven't done this myself, but there seem to be solutions (one that involes defining a custom ModelManager for the model in question, and another one that relies on admin interface magic): Django admin: how to sort by one of the custom list_display fields that has no database field

The problem in your case is that the model in question is the User model, which is probably not a good idea to change. In your case, I'd suggest for adding a custom UserProfile model, as described here: Django user profile

If you need to query by this value frequently, I'd suggest to materialize the pinCount value for each user in your user profile model. Depending on your requirements you could use a database trigger to keep this value updated.

Community
  • 1
  • 1
bes
  • 241
  • 3
  • 3