Django: Model attribute looks for field works in view, but not in template

63 Views Asked by At

Say I have a model:

from django.db import models

class Foo(models.Model)
    fav_color = models.CharField(max_length=250, help_text="What's your fav color?")

print(Foo.fav_color.field.help_text)  # prints: What's your fav color?

Say I have a view with context:

{
    'Foo': Foo
}

And in a template {{ Foo.fav_color.field.help_text }}, the result will be blank. However {{ Foo }} will print the string representation of the model, so I know the models is getting passed into the template.

Why are the attributes look ups to get the help_text failing in the template, why is the help_text empty in the template?

2

There are 2 best solutions below

4
Sunderam Dubey On

Maybe the template engine is considering Foo.fav_color as a string instead of model field.

When you pass the Foo model to the template, the string representation of the model that includes its class name and primary key value is automatically generated by Django. So, the moment you do {{ Foo }}, Django displays string representation of the Foo object, which is different from accessing the fav_color field.

Solution:

You can directly pass help_text in template so:

{
    'fav_help_text': Foo.fav_color.field.help_text
}

Then, access help_text in template only through {{fav_help_text}}

Edit

There is no view associated with this code, its actually a custom rendered template, with a context, that is rendered before run time.

You can define a context processor to include the Foo model instance in the context of every request so:

from myapp_name.models import Foo

def foo_context_processor(request):
    return {'Foo': Foo}

Then add this to TEMPLATES in settings.py so:

TEMPLATES = [
    {
        # ......
        'OPTIONS': {
            'context_processors': [
                # ......
                'myapp.context_processors.foo_context_processor',
            ],
        },
    },
]

Now, With this context processor, the Foo model instance will be included in the context of every request, then simply do the following in template:

{{ Foo.fav_color.field.help_text }}
0
run_the_race On

In the end I just circummed and created a custom template tag:

register = template.Library()

@register.simple_tag
def get_help_text(model, field_name):
    return model._meta.get_field(field_name).help_text

In template:

{% get_help_text Foo 'fav_color' %}