Opened 3 days ago

Closed 3 days ago

Last modified 2 days ago

#35765 closed Uncategorized (wontfix)

Change label of list_display with __ lookup to only show the bit after the __

Reported by: Kevin Renskers Owned by:
Component: contrib.admin Version: 5.0
Severity: Normal Keywords:
Cc: Natalia Bidart, Tom Carrick Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In Django 5.1 ticket #10743 was implemented: ModelAdmin.list_display now supports using __ lookups to list fields from related models. This is great!

However, the default label in the admin list is the full thing, which can get very long and wordy. For example in my UserAdmin config I can add account_settings__pace_account_id to the list_display (the User model has a one-to-one relationship with an AccountSettings model). The label in the Django Admin then becomes "ACCOUNT SETTINGS PACE ACCOUNT ID" which is extremely long. I would've expected it to be simply "PACE ACCOUNT ID".

So the result is that I am never using the new double underscore lookup feature for list_display, and instead I am still creating small getter functions like this:

def pace_account_id(self, obj):
    return obj.account_settings.pace_account_id

Is there any chance that the way the label for double-underscore-containing list_display values is generated could be changed, so that only the bit after the double underscore is shown?

Change History (8)

comment:1 by Sarah Boyce, 3 days ago

Cc: Natalia Bidart Tom Carrick added
Resolution: wontfix
Status: newclosed

Here is a tweak to a current test to show the headers:

  • tests/admin_changelist/tests.py

    a b class ChangeListTests(TestCase):  
    17051705        response = m.changelist_view(request)
    17061706        self.assertContains(response, parent.name)
    17071707        self.assertContains(response, child.name)
     1708        self.assertContains(response, '<a href="?o=1">Name</a>')
     1709        self.assertContains(response, '<a href="?o=2">Parent  name</a>')
     1710        self.assertContains(response, '<a href="?o=3">Parent  parent  name</a>')
    17081711
    17091712    def test_list_display_related_field_null(self):

Adding the relationship reduces the chance of duplicate header names. This proposal would mean the above example would have three headers called Name
I would maybe have a preference of having the labels like Name (Parent) and Name (Parent - Parent) and so from your example PACE ACCOUNT ID (ACCOUNT SETTINGS)

I have cc-ed some folks involved in the feature and it might be worth moving the discussion to the Django Forum.
It's not a clear to me that we should drop the relationship by default, just because it is long. So for now I will "wontfix" the ticket but it can be reopened after a discussion

comment:2 by Kevin Renskers, 3 days ago

Not sure if duplicate names are an actual problem in real world projects. And maybe you could only add the parent name in case there are duplicates? The length of showing the whole thing is definitely a real world problem though. In my Django projects I'm literally not able to use this double underscore feature because the labels just get way way too long, and I've never run into duplicate labels. Not saying it won't happen for anyone, but to me this feature seems to only work in the 20% rather than the 80%.

comment:3 by Tom Carrick, 3 days ago

Not sure if duplicate names are an actual problem in real world projects.

They certainly are. I can imagine having an article name with a category name quite easily, for example. I would actually like the header here to be "category" and not "name" - so the opposite of your proposed fix.

As the fix is quite simple - as you mention, and it can cause some ambiguity and be the opposite of what you want, I don't think this is the fix.

I'm not saying there isn't a fix, I do agree that this can lead to quite long table headers and cause problems, but I don't think it's this. And it might just be to let projects handle it themselves.

But if we want to have this discussion, I agree, a forum post is the place.

Last edited 3 days ago by Tom Carrick (previous) (diff)

comment:4 by Kevin Renskers, 3 days ago

Is there an easy way to hook into Django's code that generates the labels, so I can override this behavior for my own projects?

comment:5 by Tom Carrick, 3 days ago

Yes. In fact before this feature it was the only good way to do it. The downside is you will need to define your own ordering and so:

@admin.display(description="Category", ordering="category__name")
def category_name(obj):
    return obj.category.name


class ArticleAdmin(admin.ModelAdmin):
    list_display = [..., category_name]
    ...
Last edited 3 days ago by Tom Carrick (previous) (diff)

comment:6 by Kevin Renskers, 3 days ago

No sorry, I meant the way labels for the double underscore values are automatically generated by Django itself. So that I can use the double underscore list_display values throughout my project, and just override (in a single place) the way these labels are generated.

comment:7 by Tom Carrick, 3 days ago

This is getting more into a usage question. but from what I recall from a quick skim of the code, there's no obvious point to override this as the code needed to be spread around a bit. I would advise looking at the PR at this point: https://github.com/django/django/pull/17357/files#diff-b674f0aa1b54dddf7406424ce5f6fc103526a35b4238d6e35cf2ab715c09455bR93

Regardless, I don't think there's anything Django should do here.

comment:8 by Kevin Renskers, 2 days ago

Just in case anyone else runs into the same problem of long labels and wants to change it, I found a solution: https://www.loopwerk.io/articles/2024/changing-django51-lookup-labels/.

Note: See TracTickets for help on using tickets.
Back to Top