#5863: list_display does not allow functions of references objects
---------------------------------------------+----------------------------- -
Reporter: Beat Bolli <me+dja...@drbeat.li> | Owner: nobody Status: new | Component: Admin interface
Version: SVN | Keywords: list_display Stage: Unreviewed | Has_patch: 0
---------------------------------------------+----------------------------- -
It is possible to include a model member function in the list_display
Admin property. The same thing is not possible for ForeignKey models; at
least not with any of the variations I have tried: foreign.method,
foreign_method and foreign__method.
> It is possible to include a model member function in the list_display
> Admin property. The same thing is not possible for ForeignKey models; at
> least not with any of the variations I have tried: foreign.method,
> foreign_method and foreign__method.
New description:
It is possible to include a model member function in the `list_display`
Admin property. The same thing is not possible for ForeignKey models; at
least not with any of the variations I have tried: `foreign.method`,
`foreign_method` and `foreign__method`.
Comment:
Seems like a reasonable addition to me. Do we even allow doing this for
actual fields of a related model? This feature probably needs to be part
of newforms-admin or wait until that branch is merged though. It would be
helpful if you could attach a simple example, or even try your hand at
creating a patch.
I just wanted to raise this again. I'm using the new forms admin branch
and it's odd that in the following
{{{
class BlueEDIJobFileAdmin(admin.ModelAdmin):
search_fields=('blueedijob__client__code',)
list_display = ('id','blueedijob__client__code',)
}}}
The search_fields option is valid, but the list_display option is not.
The patch uploaded shows the related objects field values in the same way
as the object field values are shown (a boolean as an tick icon etc.)
rather than as a string as a custom method would.
However the header of the field still shows the related object's verbose
name. Ideally it would show something like (section -> title) to indicate
its a related objects field, but I haven't worked out how to do that yet
:)
Replying to [comment:9 pihentagy]:
> What is the next step to see this patch in django?
>
Since this ticket was raised callables were added to the list of things
allowed, in list_display, as were methods on !ModelAdmin, in [8352]. Do
we need yet another way to specify something in list_display? Can this
case not be covered by callables?
I was going to experiment to see, but I can't. First, the patch doesn't
apply cleanly to existing trunk. The actual apply failures are on the
tests, not the code, so I thought I could experiment with the code, but I
can't get that to work either. If I add something with the double
underscore syntax to the list_display for one of the models in my app, I
get an !ImproperlyConfigured exception thrown during admin validation:
{{{
Traceback:
File "/home/kmt/django/trunk/django/core/handlers/base.py" in get_response
77. request.path_info)
File "/home/kmt/django/trunk/django/core/urlresolvers.py" in resolve
179. for pattern in self.urlconf_module.urlpatterns:
File "/home/kmt/django/trunk/django/core/urlresolvers.py" in
_get_urlconf_module
198. self._urlconf_module = __import__(self.urlconf_name,
{}, {}, [''])
File "/home/kmt/software/web/xword/../xword/urls.py" in <module>
9. admin.autodiscover()
File "/home/kmt/django/trunk/django/contrib/admin/__init__.py" in
autodiscover
40. __import__("%s.admin" % app)
File "/home/kmt/software/web/xword/../xword/crossword/admin.py" in
<module>
61. admin.site.register(Puzzles, PuzzlesAdmin)
File "/home/kmt/django/trunk/django/contrib/admin/sites.py" in register
76. validate(admin_class, model)
File "/home/kmt/django/trunk/django/contrib/admin/validation.py" in
validate
38. % (cls.__name__, idx, field,
cls.__name__, model._meta.object_name))
Exception Type: ImproperlyConfigured at /admin/crossword/authors/
Exception Value: PuzzlesAdmin.list_display[4], 'AuthorID__Notes' is not a
callable or an attribute of 'PuzzlesAdmin' or found in the model
'Puzzles'.
}}}
This may be validation code added since the patch was originally created,
I don['t know -- I think I specified the new thing correctly but I'm not
entirely sure because there are no docs for the new supported thing in
list_display. The existing docs spell out pretty clearly what's allowed:
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#list-display and
they would also need to be updated if it's decided this addition is still
worthwhile.
So a working patch with docs that applies cleanly to trunk (and doesn't
have the same problem with sorting that [8352] introduced, see [9212]),
plus something that addresses graham's last remark about the title for the
column being non-intuitive, are all missing for this to get in...but even
before that please answer the first question I had: what does this provide
that isn't already possible given the expanded options of things you can
now specify in list_display?
Replying to [comment:10 kmtracey]:
> but even before that please answer the first question I had: what does
this provide that isn't already possible given the expanded options of
things you can now specify in list_display?
Consistency and DRY: so you shouldn't write boilerplate code. You
shouldn't specify column name django alredy knows.
Replying to [comment:11 pihentagy]:
> Consistency and DRY: so you shouldn't write boilerplate code. You
shouldn't specify column name django alredy knows.
I understand wanting to avoid boilerplate code but I'm missing how this is
a common enough case to warrant inclusion and balance the additional
complexity (both for users -- the list of things you can put in
list_display is getting a bit long -- and code maintainers). What's the
common situation where user's would really like to see the value of a
field in a related model instead of just the text representation of the
related model? I'm just not seeing that as a very common need, meaning
when you need it if you have to write a little extra code it's no big
deal. It's not boilerplate if you only have to do it in rare situations.
I'm looking for something a little more concrete as motivation than mom
and apple pie goodness.
Replying to [comment:12 kmtracey]:
> Replying to [comment:11 pihentagy]:
> > Consistency and DRY: so you shouldn't write boilerplate code. You
shouldn't specify column name django alredy knows.
>
> I understand wanting to avoid boilerplate code but I'm missing how this
is a common enough case to warrant inclusion and balance the additional
complexity (both for users -- the list of things you can put in
list_display is getting a bit long -- and code maintainers). What's the
common situation where user's would really like to see the value of a
field in a related model instead of just the text representation of the
related model? I'm just not seeing that as a very common need, meaning
when you need it if you have to write a little extra code it's no big
deal. It's not boilerplate if you only have to do it in rare situations.
I'm looking for something a little more concrete as motivation than mom
and apple pie goodness.
If you have just 1 or 2 foreign keys, you have a lot of place, so it seems
logical to display more interesting fields from a foreignkey. The unicode
representation is ok, but it is just 1 column, you will find things
quickly, if you have 2 or 3 fields from a foreign tabble (not to mention,
you will be able to sort on that field for free!)
For example m2m tables with additional fields doesn't contain interesting
information on their own. Maybe you want to display more columns from one
FK and sort on them...
Replying to [comment:13 pihentagy]:
> What's the common situation where user's would really like to see the
value of a field in a related model instead of just the text
representation of the related model? I'm just not seeing that as a very
common need, meaning when you need it if you have to write a little extra
code it's no big deal. It's not boilerplate if you only have to do it in
rare situations. I'm looking for something a little more concrete as
motivation than mom and apple pie goodness.
Can I add that I would very much like this functionality for my project.
In fact the lack of this functionality led me to give up on the admin
interface and create my own thing that did do that!
Being able to mix-in related model fields is very useful for creating a
'dashboard' style admin page which I would think is a very common
requirement.
Replying to [comment:14 danros]:
>
> Can I add that I would very much like this functionality for my project.
In fact the lack of this functionality led me to give up on the admin
interface and create my own thing that did do that!
It was easier to write your own admin than write some trivial !ModelAdmin
methods that returned the information you were interested in?
Replying to [comment:16 pihentagy]:
> Should I open a ticket for that, or is there one for it?
I believe that is what this ticket is asking for, so no need for another
ticket. In the absence of a working patch for this ticket, you can
achieve what you want by adding !ModelAdmin methods (or callables) that
return the information you are looking for, and specifying these methods
in your `list_display`. It is not particularly difficult and not a lot of
code. Doc is here: http://docs.djangoproject.com/en/dev/ref/contrib/admin /#list-display
I'd say this ticket can be closed (I found it when looking for material
related to #10230).
Using callables (bare functions for example, i.e. no model methods nor
`ModelAdmin` subclasses methods) make the "It violates DRY: I have to
define the same function on each model that references the foreign model"
argument moot.
Also, when it comes to the HTML table headers:
1. Seeing a bare 'Code' header (using the
[http://code.djangoproject.com/ticket/5863#comment:6 comment 6] example)
that refers to a `code` field of a `Client` model that is located one or
more FK-hops away isn't necessarily a good idea, it can be confusing
because the user could assume it refers about a (non-existent) `code`
field local to the model being displayed.
2. In the case of more that one level of indirection, having an
automatically-generated `'Hop1 Model > ... > HopN Model > Field'` header
wouldn´t be practical/scalable.
It's more practical in that case that the developer sets explicitely an
appropiate, unambiguous header literal using the `.short_description`
facility.
In other words, I'd say current functionality plus a bit of work satisfy
the needs expressed in this ticket discussion for this arguably rare
scenario.
Reasons not to close this ticket:
- consistency between search_fields, list_display, and list_filter: it
seems reasonable to want them all to work the same way. At the basic
level, they are all a list of fields, after that, the limitations seem
arbitrary (i.e. it seems at first glance as if the more advanced features
of each could be available but just haven't been programmed yet).
- this need isn't really so rare, particularly if you have models that
relate one-to-one, where you naturally do want to include fields from
across several tables.
Would someone like to review the snippet I've come up with as a "work
around" of sorts? It would definitely need some work before it could be
used in Django if it's deemed worthy, but I hope it's an option at
least... I'm not sure I feel comfortable posting it as a patch because of
the issues involved with my approach, but I still think it's worth looking
at.
One thing that I think no one has pointed out yet; if it were possible to
set {{{table__field}}} in list_display, you could order the list by that
field in the interface, which you can't do with callables.
Replying to [comment:22 haffi67]:
> One thing that I think no one has pointed out yet; if it were possible
to set {{{table__field}}} in list_display, you could order the list by
that field in the interface, which you can't do with callables.
You can set admin_order_field on a callable to specify ordering; doc on
that is the last bullet under
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contri....
If that doesn't currently support the double-underscore syntax to
reference a ordering by a field in a related object, then I doubt it would
'just work' for things specified that way in list_display.
Seems like discussion of this has petered out. Too bad, especially when
more and more people are looking to subclass parts of admin for their own
use.
This is so simple in many other ways in admin. I realize it leads to
situations where what you get back isn't a field, but another queryset,
but the developer gets what they deserve in that case. Its not hard (or
even out of precedent) to simply ignore relations which are nonsense. Just
take a look at the behavior of select_related! Having to create a custom
method each time is tedious and this limitation prevents extensibility in
situations where you've put those fields on the model yourself manually
using extra() and other methods.