Django patterns and spaces

I started using custom inclusion tags in my django templates. For example, I have a tag {% profilelink profile %} that inserts a link into the user profile along with a small version of the profile image, for example (profilelink.html):

 <a href='{% url ... %}'><img src='{{ ... }}' alt='...'> {{ profile.name }}</a> 

However, when I use it in the following snippet (sometemplate.html):

 <p>Owned by {% profilelink owner %} (uploaded by {% profilelink uploader %})</p> 

Then I get a space between the HTML created by the second template tag and the closing parenthesis. This gap is undesirable. It comes from the last newline in the profilelink.html file. This is a very common problem, and Stackoverflow search gives a lot of questions about spaces in templates in general. Here is a summary of the solutions found so far and why they do not work:

Some of these problems are resolved by the {% spaceless %} tag, but not all of them. This tag only removes spaces between tags , which does not match the example above.

One possible solution is to not have a final EOL in profilelink.html, but this is highly undesirable. Reasons: this is generally a bad style; some editors (vim) silently add back by default; that POSIX defines a string ; this may make some SCM unhappy; and etc.

Another solution is to switch to another template engine, such as Jinja2 , which may or may not solve this problem. It supports constructs like {% ... -%} , which are fed by the next EOL character. This is useful in some situations, but also useless for my example above. But switching templates for such a little annoyance seems a bit overkill and adds another dependency. I would like to stick to what is the standard way of "django". Apparently, it is planned to make Jinja2 the new Django standard.

Some people suggested using a middleware class to remove excess space from the generated HTML before sending it to the browser. This is useful, but only for converting HTML in a way that is functionally equivalent, i.e. The same semantics: it will still display the same in the browser. This is not what I want, I want the actual change in semantics so that it displays correctly. This is not possible to implement in a common middleware class. I need to have control over this in each case from the template itself. I don’t care about making HTML more beautiful, I care about it being correct in the first place.

There is also bug # 2594 , which was closed as WONTFIX with the argument (quote) "the Django template language is good enough to generate HTML that is not space-sensitive." In my guess, this is just completely wrong. HTML is very space-sensitive; it doesn't care how much is from it. He cares a lot about whether there are any gaps or not at all.

Some kind of my question: is there any reasonable way to fix this problem at all? (One that always works, not just in some situations.)

(All CSS-based fixes are not taken into account. Copying / pasting surprises is evil.)

+5
source share
2 answers

I believe one solution is to use simple_tag instead of the inclusion shortcut, hopefully without much clutter.

I assume your tag looks something like this:

 @register.inclusion_tag('profilelink.html') def profilelink(user): return {"profile": user} 

Is it possible to replace this with

 from django.template.loader import render_to_string @register.simple_tag def profilelink(user): t = render_to_string("profilelink.html", {"profile": user}) return t.strip() 

I do not have a Django project right now, so it has not been verified.

+2
source

This is the best I've come up with so far. I still hope for a better solution, but for now it will be done.

I defined a custom filter like this in base / templatetags / basetags.yp ( taken from this answer ):

 from django import template from django.template.defaultfilters import stringfilter register = template.Library() @register.filter @stringfilter def trim(value): return value.strip() 

And then use it like this:

 {% load basetags %} <p>Owned by {% profilelink owner %} (uploaded by {% filter trim %}{% profilelink uploader %}{% endfilter %})</p> 
+1
source

All Articles