#4829 closed (wontfix)
verbose_name(_plural) not accessible in templates (contrib.contenttype)
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Contrib apps | Version: | dev |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Design decision needed | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I created an history application similar to http://code.djangoproject.com/wiki/FullHistory, so I have a table with a generic relation (object_id and content_type-fields). Now I created a template that should list all recent changes. As the content-type differs I want to this it in the output. But {{ entry.content_type.model_class._meta.verbose_name }}
ist not accessible as "_meta" begins with an underscore.
As I did not find any way to get to verbose_name while dir()'ing through the Model-classes, I created a small patch that adds model_verbose_name() and model_verbose_name_plural()-methods to the ContentType-Model. So this is possible: {{ entry.content_type.model_verbose_name }}
As I know this is redundant and will not be needed by many people I think the chances to get this into the trunk are not that big. On the other hand it does not change many things.
Attachments (1)
Change History (8)
by , 17 years ago
Attachment: | django-content-type-verbose-name.diff added |
---|
comment:1 by , 17 years ago
Triage Stage: | Unreviewed → Ready for checkin |
---|
comment:2 by , 17 years ago
Sorry to interrupt... :)
After using my patch above a while I figured, that it has a serious disadvantage: You are only able to print the model-name _if_ you use ContentType
.
So I created a filter that does the same:
from django import template from django.utils.encoding import smart_str register = template.Library() def model_verbose_name(obj): return obj._meta.verbose_name register.filter(model_verbose_name) def model_verbose_name_plural(obj): return obj._meta.verbose_name_plural register.filter(model_verbose_name_plural)
Of course it would be nice to have access to the two attributes without using a filter, but I think this is enough for most people. And because it is in its own template-filter module here I added these two, too:
def order_by(queryset, arg): order_by = arg.split(',') return queryset.order_by(*order_by) register.filter(order_by) def filter(queryset, args): args = args.split(',') kwargs = {} for arg in args: if '=' in arg: k, v = arg.split('=', 1) kwargs[smart_str(k)] = v return queryset.filter(**kwargs) register.filter(filter)
Because its nice to use this methods inside the template, mainly for some generic templates that should/could not get all possible parameters passed otherwise. With this you can use relations inside templates:
{{ user.logentry_set|order_by:"-action_time"|filter:"action_flag=1"|slice:":5" }}
This now can be added to some generic template (e.g. a base-template that displays some log inside some sort of menu) without having to create the right list in every single view. And because the relations are there I don't see any reason not to use them this way.
If mainstream is interested I will provide a patch for this. ;-)
(Would put it into its one template-module so it is not loaded everywhere. Hope this is not possible using some existing code, didn't find anything.)
comment:3 by , 17 years ago
Triage Stage: | Ready for checkin → Design decision needed |
---|
This needs more thought. David's previous comment is correct: it's going to lead to potential confusion if this is only available sometimes.
I'm almost tempted to say we don't need anything and if somebody wants this, they can write their own filter for it. At the moment, I'm probably -0 on making any change at all, but let's leave it for a little bit and see if somebody comes up with a good idea about how to integrate this. Things that won't work are promoting verbose_name or any method like that to be a method or attribute on the model instance itself (we deliberately try to avoid polluting the object namespace like that).
comment:4 by , 17 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
Agreed with Malcolm: if you need this in your template, write a filter.
follow-up: 6 comment:5 by , 15 years ago
I'm new to django and really don't get the concept yet but I was confused that in the documentation verbose_name seams to be an attribute of a class like here:
http://docs.djangoproject.com/en/1.1/topics/db/models/#topics-db-models
Section: Verbose field names
I'd at least liked the documentation to tell it's a meta option at this point
comment:6 by , 15 years ago
Replying to fexor:
in the documentation verbose_name seams to be an attribute of a class like here:
http://docs.djangoproject.com/en/1.1/topics/db/models/#topics-db-models
Section: Verbose field names
I'd at least liked the documentation to tell it's a meta option at this point
The section you point to is about field verbose names. The verbose_name
and verbose_name_plural
Meta options are about model verbose names.
comment:7 by , 15 years ago
Another idea would be a simple template tag that fetches the verbose_name or verbose_name_plural, and renders the text. This is useful for the django.views.generic.list_detail.object_list view.
@register.simple_tag def object_count(paginator): if paginator.count == 1: name = paginator.object_list.model._meta.verbose_name else: name = paginator.object_list.model._meta.verbose_name_plural text = ungettext_lazy('%(count)d %(name)s', '%(count)d %(name)s', paginator.count) % {'count': paginator.count, 'name': name} return text
The tag can be called from the template context as {% object_count page_obj.paginator %}
since the generic view automatically populates the the page_obj variable.
Was tempted to just promote to design decision, but I'll make the decision (a committer can always override me :)).
If people are using the
ContentType
model then it could be useful functionality. It's not much bloat so I say it's good.