Add {% withdict %} and {% withlist %} tags to allow creating dicts and lists in templates

So this one may have been discussed before and I’m sure this feature was rejected before it may look like a antipattern and data should be computed in the view.

However, I feel like there are very valid use cases for creating lists and dicts locally in the template.

Ok, first, there is already the `{% with %} tag allowing to declare variables in context. And there may be use cases where the template needs to transform on or several variables in a list or a dict but pre-computing them in context is just code noise.

This is what I propose:

{% withdict key1=some_variable key2=some_other_variable as my_dict %}
   {{ my_dict.key1 }}
{% endwithdict %}
{% withlist variable1 variable2 variable3 as my_list %}
  {% for var in my_list %}
    {% include "some/template.html" with tpl_var=var %}
  {% enfor %}
{% endwithlist %}

I understand that {% cycle %} may fill the same use that {% withlist %} however — and this is personal test here — I don’t fully understand how it work. Plus it may be disturbing to use {% with %} to declare a simple var, {% withdict %} to declare a dict variable but {% cycle %} to declare a list so I think {% withlist %} has a place here, may it be just an wrapper around {% cycle %}.

You can build this yourself and if you find it useful a lot, you can suggest it then?

I did build it myself and found it useful which is why I propose this addition to the community because I think it may be useful to other ppl.

1 Like

To be honest I dislike the with-tag already due to the extra indentation it comes with. I’d prefer a syntax along the lines of the set-tag that Jinja uses

Sure, me too. But I feel like that should be another discussion entirely.

Historically these kind of easy user-land tags have been suggested to be project level, simply not to grow the surface area of the built ins too far/indefinitely. It’s similar to Database Functions, which again are quite trivial but almost unbounded in potential number.

I understand. However, I feel like the current Django templating system often gets in my way. I miss some basic features that Jinja provides:

  1. being able to set abitrary variable in context from the template, in particular lists and dict,
  2. being able to access items of an object by variable content and not just name, i.e {{ my_dict[key_var] }}
  3. Being able to control whitespaces in tag like Jinja does with {{- -}} and is a especially handicaping when formatting text.

I know that the rationale is to keep the templating language as simple as possible, that it is only target at formatting HTML and that I can use Jinja instead. But Django’s template engine is so dominant in the ecosystem that adopting Jinja for a project is costly.

I really think that Django template engine could greatly benefit from providing some of these features.

2 Likes

@christophehenry I don’t know what to say. This kind of point is as old as the DTL itself. It’s not going to become Jinja (and nor should it)

All I can think to do is link you to design philosophies page.

Django’s template engine is so dominant in the ecosystem that adopting Jinja for a project is costly.

Yes, I get that. But I’d suggest the reason it’s dominant is (both) that it’s fine, and that the things you miss from Jinja don’t actually matter all that much. (When 1.8 was released a great migration to Jinja was foretold… — needless to say, it never happened.)

I still think the current implementation does not meet the current design philosophy. For instance, being unable to control whitespaces generated by tags makes it practically unusable for rendering plain text.

{% for item in items %}
- {{ item }}
{% endfor %}

Will generate:


- one

- two

- three

- four

- five

Which is not a text you want to send in an email.

{% for item in items %}- {{ item }}{% endfor %}

Will generate - one- two- three- four- five. So the only solution you have to get a proper list is either:

{% for item in items %}
- {{ item }}{% endfor %}

Which is not easy to read and will probably get flagged by Djade or djLint.

As for being able to declare and manipulate lists from template, it’s just a matter of simplicity and efficiency. I just don’t want to have to always precompute and transform data in the get_context(). It’s not always useful (for instance if you determine inthe template if you are going to display the data or not) nor it is handy. For instance, you may want to use the same view, and thus the same get_context() with different template that will display the same data differently. Sometimes, only the template knows how it wants the data to look like.

1 Like

Can you expand on what happened with 1.8 release? I wan’t even a developer then.

Support for multiple template backends (basically Jinja) was added

+1 here. The DTL isn’t perfect, but you can “DIY” with custom tags and filters. withdict and withlist seem a bit niche to include as builtins.

Yes - see the release notes. They’re all still there!

Not by Djade—I designed it specifically to avoid altering rendered output.

I could get behind a {% set %} tag proposal like Jinja’s if we start that discussion.

1 Like

I think there’s also a bit of “it’s always been like this” motivation behind some decisions in Django templates that imo does not suit the current community anymore. The idea that templates are written by designers and not programmers is the basic cause. I would hazard a guess that ~zero% non-programmers write Django templates nowadays, even if that did happen 20 years ago at the start.

If we agree that this idea is of the past, and not the present, I think we could move forward.

2 Likes

Alright I started this discussion.

imo i think reducing complexity in templates will lend to better code, interesting idea though

I’m -1 to withdict and withlist. My reasons:

  • This feels like an unpolished API and it does not scale. For example, future users can come and ask for withset, withstr, etc. that follow this pattern.
    • Also I think this leaks logic into the templates and could potentially confuse new users.
  • I have use Django to develop medium and large projects and not once I’ve needed something like this. I know this does not qualify as an objective counterargument, but I think it does show a difference in programming patterns. Perhaps the need of such logic in a template may indicate that a different approach is taken in the views? My preferred style (because it’s more testable, it scales better, it encapsulated logic) is to have these required constructs as either:
    • Model instance (cached) properties (when it makes sense and when the logic belongs in the Model)
    • Context attributes
  • Adds extra burden of maintenance and documentation to the project for a non clear general benefit.

To me, isolating business logic to python layers and not having those in the templates is “a must”. Maybe it would help the conversation to read 2-3 use cases for these proposed tags? Those would show what pattern or what approach justifies these tags not violating encapsulation of logic?

Lastly, and as it was suggested in other posts, perhaps this could be first presented as a third party app? “django-extra-tags-and-filters” perhaps?

PS: As a side note, I’ve encountered the need to use the add filter beyond numbers. It would be beneficial to enhance it to mimic Python’s + operator for a more natural and expected behavior.

1 Like

I suppose this thread can be closed, then.