Code

Opened 4 years ago

Last modified 6 months ago

#14336 new New feature

list_display should be able to contain sortable references to extra and/or annotated fields

Reported by: pmclanahan Owned by: nobody
Component: contrib.admin Version: 1.2
Severity: Normal Keywords:
Cc: riccardo.magliocchetti@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Overriding the queryset method of a ModelAdmin should be an easy way to annotate the QuerySet used in the admin list view for a model. My use case is that I have two IntegerFields containing counts of various things, but what I'd like to be able to display and sort by in the admin list view is the sum of these two fields. This can best be explained by an example:

# Given this model
class Article(models.Model):
    title = models.CharField(max_length=255)
    num_a = models.PositiveIntegerField()
    num_b = models.PositiveIntegerField()

# Want ModelAdmin like...
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title' 'total_nums')
    
    def queryset(self, request):
        qs = super(ArticleAdmin, self).queryset(request)
        return qs.extra(select={'total_nums':'num_a + num_b'})

This fails at model validation with a ImproperlyConfigured exception in django.contrib.admin.validation.validate because the model has no 'total_nums' field, which we know. But the model validation mechanism has no access to the instance of the ModelAdmin, and therefore no access to the queryset to be able to check for any extras or annotations.

I tried fixing this and would have submitted a patch, but I failed in the time I had. However, there is a workaround I discovered and am using, but it seems silly. You change ArticleAdmin to the following:

class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title' 'total')
    
    def total(self, obj):
        return obj.total_nums
    total.admin_order_field = 'total_nums'
    
    def queryset(self, request):
        qs = super(ArticleAdmin, self).queryset(request)
        return qs.extra(select={'total_nums':'num_a + num_b'})

This seems overly verbose and a little hacky, but it does work. I'd say that makes this ticket non-urgent, though I do wonder how many developers gave up before discovering this technique.

Attachments (0)

Change History (5)

comment:1 Changed 4 years ago by DrMeers

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

We don't really want to encourage the use of extra in general, however making additional queryset attributes available in list_display could be quite useful when used in conjunction with annotate.

comment:2 Changed 3 years ago by graham_king

  • Severity set to Normal
  • Type set to New feature

comment:3 Changed 2 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:4 Changed 2 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:5 Changed 6 months ago by rm_

  • Cc riccardo.magliocchetti@… added

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as new
The owner will be changed from nobody to anonymous. Next status will be 'assigned'
as The resolution will be set. Next status will be 'closed'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.