Provide a standard integrated way to use presenters in DTL

It’s not uncommon to use the same template with different data or different model that represent similar concepts and should be disaplyed the same in the template, but that, but legacy reasons, for instance, do not have the same topology. To solve this, RoR has presenters that act as an interface between the data and the template. I think Django should provide a similar and integrated mecanism.

Other solutions that may work but were rules out:

  • transform the data in get_context()
    iterate through data (for instance query results) twice (one to transform them in get_context(), the other to display them in the template) is inefficient
  • write a specific tag or filter
    tags and filters are supposed to be chunks or reusable code, not bandaid to patch a DTL missing feature.

On solution could be to let app declare presenters in a presenters.py and/or, views in View.get_presenters(). Those presenters would be automatically be added to the template context and made available to the template with a filter:

{% for obj in qs.all %}
    {% with obj=obj|presenter:MyPresenter %}
        {# do templating here #}
    {% endwith %
{% endfor %}

This is rather abstract. What exactly does a presenter do? Take a dict, transform it, and return a new dict?

I’m going to put out the normal line here of this ought to be a package before being considered for core.

The thing that concerns me with the example above is how it would optimize queries and/or flag N+1 queries from happening which is all to easy in a template, but even more so when going back to a template tag or other python logic.

Take a dict, transform it, and return a new dict?

Doesn’t have to be a dict. Any object, in or out can do the trick.

This is rather abstract.

Which is why I’m bringing this to the community to see if anyone else has this problem and/or ideas on how to solve it.

You can already do this yourself right? You can pass the MyPresenter variable in the context, or even insert such objects via a context processor, and the filter presenter is trivial.

I do like the idea of passing tranformer functions into the context like this though… reminds me of something else we discussed on this forum last week.

Presenters here look like (one half of) the View Model in the Model–View–Viewmodel pattern, or what Martic Fowler called a Presentation Model.

Use of such can certainly be of help if you’re wanting somewhere to keep formatting logic (italics, because it can be anything…) that’s not model methods, or template tags, or get_context_data methods (those being the cited places that such logic often first goes).

I often use an attrs class for such display helpers — lightweight wrappers that can encapsulate related bits, behind a nice object-like API.

This point of @nanorepublica’s is dead right. There would be a lot of experimentation to be done here, and one idea would stimulate many others. Quick release cycles and a lack of backwards compatibility concerns would be for the win. An established (settled) candidate would need to be in place before merging anything to Django would be appropriate.

It’s almost better to discuss this as, “Any ideas of how to do…?” in the Using Django category, for that reason. Otherwise it feels like a constant stream of just saying No, whereas (rather) this is an interesting topic.

1 Like

A construct which takes some data, reshapes it to its needs, and uses it to render a template? This sounds very similar inclusion_tag to me. Granted, the tag takes a dict of context, but just passing in a single model instance as a pattern would give you 99% of this pattern in Django today.

I think an inclusion tag doesn’t qualify as using it would become spaghetti code: single use tags defined far from the view/template that needs it (although, one can argue that view/template far from each other has some of that problem already).