[Django]-Model name of objects in django templates

72đź‘Ť

âś…

object.__class__.__name__ or object._meta.object_name should give you the name of the model class. However, this cannot be used in templates because the attribute names start with an underscore.

There isn’t a built in way to get at that value from the templates, so you’ll have to define a model method that returns that attribute, or for a more generic/reusable solution, use a template filter:

@register.filter
def to_class_name(value):
    return value.__class__.__name__

which you can use in your template as:

{{ obj | to_class_name }}
👤Shawn Chin

7đź‘Ť

You cannot access the class name directly. Doing something like this:

{{ object.__class__ }}

will cause a TemplateSyntaxError: Variables and attributes may not begin with underscores. Django doesn’t let you access those sorts of attributes – Python conventions means they are hidden implementation details, not part of the object’s API.

Create a template filter instead, and then you can use it as follows:

{{ object|model_name_filter }}

Creating filters is very easy: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/

👤Gareth

4đź‘Ť

Django added a publicly accessible API to model options called _meta, but you still can’t access variables with an underscore in the template. Use a template filter:

@register.filter
def verbose_name(instance):
    return instance._meta.verbose_name

In the template:

{{ instance|verbose_name }}

I even like to chain the title filter to capitalize the words in the my template:

{{ instance|verbose_name|title }}
👤Bobort

1đź‘Ť

Since 1.2 version and may be early Django has an attribute opts into templates. The atribute is link to model._meta For evidence you should look at source code into Github

It used into template very simple: {{opts}} or {{opts.db_table}}

0đź‘Ť

You can very easily access the content type of the page, this way you don’t even need to poke into the specific:

{% if pub.content_type.app_labeled_name == 'home | publication' %}
    {% include "home/publication.html" with pub=pub.specific %}
{% endif %}
👤Rémy

0đź‘Ť

This answer demonstrates a practical use case. In my app each model has a generic.CreateView named name=”<model>-create” in urls.py; namespaced/referenced as {% url <app>:<model>-create %} in those templates which need to link to it. Each model has a generic.ListView rendered by <app>/templates/<app>/<model>_list.html. I wanted to include a button at the bottom of each rendered list view to link to the corresponding create view. To ensure consistency across multiple list views I wanted to do this in a base template which each list view template could extend upon. To do this I needed to be able to reference the model name in a template. Here’s how I did it.

$ mkdir <app>/templatetags
$ touch <app>/templatetags/__init__.py
$ vi <app>/templatetags/tags.py

from django import template
register = template.Library()
# this filter allows any template to reference an instance’s model name as <instance>|class_name
@register.filter(name="class_name")
def class_name(instance):
    return instance._meta.model.__name__

$ vi <app>/templates/base_list.html

~
{% with name=object_list|first|class_name|lower %}
        <button onclick="location.href='{% url request.resolver_match.app_name|add:':'|add:name|add:'-create' %}';" title="create"><i class="fa fa-plus"></i></button>
{% endwith  %}

* substitute <app>, <model>, and <instance> for your own names.

👤Clarius

Leave a comment