Opened 8 years ago

Last modified 8 years ago

#26524 closed Cleanup/optimization

Change foreign key id list_display reference to display only the id — at Version 11

Reported by: Cristiano Coelho Owned by: nobody
Component: contrib.admin Version: dev
Severity: Release blocker Keywords: admin list_display changelist
Cc: Cristiano Coelho, krishna.bmsce@…, zachborboa@… Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Tobin Brown)

Given these two models.

class A(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name

class B(models.Model):
    name = models.CharField(max_length=100)
    fk = models.ForeignKey(A)
        
    def __unicode__(self):
        return self.name

And these model admin

class AAdmin(admin.ModelAdmin):
    list_display = ('id','name')
admin.site.register(A, AAdmin)

class BAdmin(admin.ModelAdmin):
    list_display = ('id','name','fk_id','fk')
admin.site.register(B, BAdmin)

As you see, for BAdmin I'm trying to display the actual id of the foreign key, so I prevent an additional unwanted join (or worse, one query per related object if no select related is added). However, the admin page refuses to display the id and instead renders the whole object (calling the unicode method) which causes the additional join I don't want.
In order to demostrate it I also added the 'fk' relation which works as expected

The change list result is then

1	test B	test A	test A

where it should be

1	test B	1	test A

In order to work around it, I can define a callable that just returns the id property, but that's terrible because I lose any sort option on it plus I need to write quite a few more lines.

Change History (11)

comment:1 by Tim Graham, 8 years ago

Summary: Django Admin list_display - Unable to display foreign key idChange foreign key id list_display reference to display only the id
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

Seems reasonable, though is backwards-incompatible -- hopefully not too many people will be affected by the change but I'd mention it in the release notes.

comment:2 by Cristiano Coelho, 8 years ago

Is there any specific reason that using 'fk_id' and just 'fk' causes both to actually fetch the object? I'm expecting that if I access fk_id I am actually accessing the attribute and not the relation.

It is the same case when working with instances:

b = B.objects.first()
print b.fk_id --> prints the id/value
print b.fk --> fetchs the relation and call the actual object __unicode__

So for me this working different when using the ModelAdmin and display_list looks like a bug rather than a cleanup, you have two properties performing the exact same action.

comment:3 by krisys, 8 years ago

@cristianocca and @tim, the has_related_field_in_list_display method of ChangeList class in django.contrib.admin.views.main makes use of the django.db.models.options:Options._forward_fields_map which treats the _id attribute in a similar way and the same has been documented there - https://github.com/django/django/blob/master/django/db/models/options.py#L469 it specifically talks about the *_id fields as well.

Last edited 8 years ago by krisys (previous) (diff)

comment:4 by Cristiano Coelho, 8 years ago

So actually changing this could break a few things? Any other work around that could let you use the *_id field but still allow for sorting of that column, which using a custom callable prevents?

comment:5 by Tim Graham, 8 years ago

Not necessarily, changing it at the admin list_display level might be feasible.

comment:6 by krisys, 8 years ago

Cc: krishna.bmsce@… added

comment:7 by krisys, 8 years ago

@timgraham, I have submitted a pull request for the same https://github.com/django/django/pull/6497
Will be happy to know if there are any better ways of doing this.

comment:8 by Tim Graham, 8 years ago

Has patch: set

Please check "Has patch" so the ticket appears in the review queue.

comment:9 by krisys, 8 years ago

@timgraham, Thanks. Will do that from now onwards.

comment:10 by Zach Borboa, 8 years ago

Cc: zachborboa@… added

comment:11 by Tobin Brown, 8 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top