Opened 9 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 )
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 , 9 years ago
Summary: | Django Admin list_display - Unable to display foreign key id → Change foreign key id list_display reference to display only the id |
---|---|
Triage Stage: | Unreviewed → Accepted |
Type: | Bug → Cleanup/optimization |
comment:2 by , 9 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 , 9 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.
comment:4 by , 9 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 , 9 years ago
Not necessarily, changing it at the admin list_display
level might be feasible.
comment:6 by , 9 years ago
Cc: | added |
---|
comment:7 by , 9 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 , 9 years ago
Has patch: | set |
---|
Please check "Has patch" so the ticket appears in the review queue.
comment:10 by , 9 years ago
Cc: | added |
---|
comment:11 by , 9 years ago
Description: | modified (diff) |
---|
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.