Code

Opened 7 years ago

Closed 6 years ago

Last modified 4 years ago

#4829 closed (wontfix)

verbose_name(_plural) not accessible in templates (contrib.contenttype)

Reported by: David Danier <goliath.mailinglist@…> Owned by: nobody
Component: Contrib apps Version: master
Severity: Keywords:
Cc: Triage Stage: Design decision needed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

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)

django-content-type-verbose-name.diff (1.2 KB) - added by David Danier <goliath.mailinglist@…> 7 years ago.

Download all attachments as: .zip

Change History (8)

Changed 7 years ago by David Danier <goliath.mailinglist@…>

comment:1 Changed 7 years ago by SmileyChris

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Ready for checkin

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.

comment:2 Changed 7 years ago by David Danier <goliath.mailinglist@…>

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 Changed 7 years ago by mtredinnick

  • Triage Stage changed from Ready for checkin to 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 Changed 6 years ago by jacob

  • Resolution set to wontfix
  • Status changed from new to closed

Agreed with Malcolm: if you need this in your template, write a filter.

comment:5 follow-up: Changed 4 years ago by fexor

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 in reply to: ↑ 5 Changed 4 years ago by ramiro

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 Changed 4 years ago by pressureman

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.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.