EDITED: updated field_value to use _get_FIELD_display() instead of getattr(). This way nice display will be done also for TextChoices. Additionally, “translate” True/False/None into Yes/No/-.
A ModelForm with read-only fields (or a widget that just renders the value) might be clearer to understand? The field would then do the verbose name for you.
But otherwise, nothing else comes to mind except listing the fields explicitly in the template
My first reaction to this is that you really don’t want to do this in the template - you’re a lot better off preparing the context directly and minimizing the amount of work done by the rendering engine.
Then I realized that this functionality looks a lot like what the Django admin does, and so I checked it out to see how it does this - and my guess was correct. The admin does all the work in the view, minimizing the effort in the template.
My suggestion would be to create a utility function to build the data to be rendered and call that in the view. It’s going to perform a lot better that way.
@Colterzamir - That’s not where you want to do that work. You want that preparation to be done in the view or as a set of model methods to be called as references in the variable tag.
As mentioned by others, this may not be the best approach. It is better to do that in view and then pass it to HTML template via context.
But if you still want to do it from templates, my example in initial post works good !
I’m new to Django, and I’m trying to understand why this should be done in the view.
Is it just because of the performance benefit, since the render() code has to parse the template language to figure out what is needed?
In my use-case, I have a side-panel template that is included by a bunch of other templates, so it looks like I’ll have to add code to a bunch of views to populate the context with what I want. If the template language had code to query the models directly, then I could get by with a lot less code.
It’s partly that, but more than just that. It’s also a general “Best-practice” for Django. The DTL is specifically designed with limitations to encourage work be done in Python and not in the templates.
If this is something appearing in multiple views, then you can use a custom context processor to make it available on every page.
This is commonly for things like menus or dynamically generated headers or footers on a page.
It’s also used for other purposes like making specific variables always available, like the currently logged-in user.
Since the context processor receives the request object as a parameter, it can also be customized to provide different values based on the URL or other attributes in the request.
Finally, if you really have unique requirements, you also have the ability to create new tags and filters to cover cases that just can’t be handled any other way.
Found this method that retrieves all fields from an instance.
Doing this on the view:
fields = model._meta.get_fields()
field_data = [(field.verbose_name, getattr(self.object, field.name)) for field in fields]
context['fields'] = field_data
and calling this on the template:
{% for field in fields %}
<li>
{{field.0}} -- {{field.1}}
</li>
{% endfor %}
shows all the fields (verbose_name, value) of a given model instance. Hope it helps!