How to display verbose_name in HTML template

I’m trying to display the verbose_name (or the default name when no verbose_name exists), in the “detail” display of a model.
I’ve tried something like this, but it doesn’t work:
{{ client.funky_field_1.verbose_name }}

models.py

class Client(models.Model):
    funky_field_1 = models.CharField("Daily living", max_length=20, default='')
    funky_field_2 = models.CharField(max_length=20, default='')

views.py

class ClientDetail(UserAccessMixin, generic.DetailView):
    model = Client
    template_name = 'clients/client_detail.html'

    def get_context_data(self, **kwargs):
        context = super(ClientDetail, self).get_context_data(**kwargs)
        context['client'] = self.object
        return context

client_detail.html

    <div class="row mb-1">
         <div class="col-sm-3 fLabel">{{ client.funky_field_1.verbose_name }}:</div>
         <div class="col-sm-9">{{ client.funky_field_1 }}</div>
    </div>
    <div class="row mb-1">
         <div class="col-sm-3 fLabel">{{ client.funky_field_2.verbose_name }}:</div>
         <div class="col-sm-9">{{ client.funky_field_2 }}</div>
    </div>

Any idea on how to programmatically make the verbose_name appear, without having to write it out for every field when displaying the info in a detail page?

What makes this tricky is that the verbose name is associated with the Model class and not with the instances of the Model.

Getting the verbose name from a model field would be done as:
Client._meta.get_field('funky_field_1').verbose_name

I’m not sure there’s really a way to directly do this in a template. You might need to collect these names in the view. (I guess you could create a custom tag for it.)

Thanks for the direction. I found some examples of where people were using template tags to get the name of a model:

Then, I was able to use the Django documentation to learn about how to create custom template tags and filters:
https://docs.djangoproject.com/en/3.2/howto/custom-template-tags/

Combining those two sources with your answer, helped me create this…

clients/templatetags/client_extra.py
(as the documentation says… don’t forget the init.py file to ensure the directory is treated as a Python package)

from django import template

register = template.Library()

@register.filter
# Gets the name of the passed in field on the passed in object
def verbose_name(the_object, the_field):
    return the_object._meta.get_field(the_field).verbose_name

In my template, I am using it like this:

{{ client|verbose_name:"funky_field_1" }}

This is working!!!

So, now I only need to figure out how to, inside the custom filter, determine if a field does NOT have a “verbose_name” present, and then display the field’s “calculated” verbose_name in “sentence case”.

For example, on a field like this in the model, it works fine, and displays the text “Daily living”:
funky_field_1 = models.CharField("Daily living", max_length=20, default='')

On a field like this in the model, it displays the field name, but in lower case, like “funky field 2”:
funky_field_2 = models.CharField(max_length=20, default='')

My “if” statement in my custom filter does not seem to help, because I’m guessing the returned verbose_name is already being calculated when it isn’t present.

@register.filter
# Gets the name of the passed in field on the passed in object
def verbose_name(the_object, the_field):
    if the_object._meta.get_field(the_field).verbose_name == "":
        return "blankety blank"
    else:
        return the_object._meta.get_field(the_field).verbose_name

In that example above, I want to see if “blankety blank” will be returned in the funky_field_2 scenario, but it just returns: “funky field 2”.

Any ideas on this last piece?

I saw that this post is getting more attention and I forgot to update how I ended up solving this.

This is the end result of the custom filter that is working:

@register.filter
# Gets the name of the passed in field on the passed in object
def verbose_name(the_object, the_field):
    # Check if the verbose name is using the default value, in which case it will be all lowercase
    if the_object._meta.get_field(the_field).verbose_name.islower:
        # Change
        return the_object._meta.get_field(the_field).verbose_name.capitalize()
    else:
        # The verbose name has been set in the model, so just display it normally
        return the_object._meta.get_field(the_field).verbose_name

The rest of the explanation is in a previous post on this same thread:
https://forum.djangoproject.com/t/how-to-display-verbose-name-in-html-template/11738/3