Remove line breaks from Django template

I needed the same, because I'm using a template to generate an email subject line (non-HTML, so {% spaceless %} is useless). In my case, the template had taken on lots of different cases, and everything had to be written in a single line over about 500 characters.

So in the spirit of {% spaceless %}, I wrote my own {% linebreakless %}:

import six
from django import template
from django.template.base import Node
from django.utils.functional import allow_lazy


register = template.Library()


@register.tag
def linebreakless(parser, token):
    nodelist = parser.parse(('endlinebreakless',))
    parser.delete_first_token()
    return LinebreaklessNode(nodelist)


class LinebreaklessNode(Node):
    def __init__(self, nodelist):
        self.nodelist = nodelist

    def render(self, context):
        strip_line_breaks = allow_lazy(lambda x: x.replace('\n', ''), six.text_type)
        return strip_line_breaks(self.nodelist.render(context).strip())

Please note that it (intentionally!) preserves all whitespace except line breaks.

An example usage for an email template would look like this, assuming the above is loaded in a template tag module called linebreakless.py:

{% load linebreakless %}{% linebreakless %}

{# Email subjects are (encoded) text, not HTML, so we don't need any autoescaping! #}
{% autoescape off %}

New Notification
 •
{% if flag %}
 about this
{% else %}
 about that
{% endif %}
!

{% endautoescape %}
{% endlinebreakless %}

Note that the {% linebreakless %} tag has to be on the first line (and after the {% load %} directives) to prevent any line breaks in the generated file.


The spaceless tag removes spaces between html tags, it's not possible to get it to remove spaces within tags, as you are trying to do.

You can prevent newlines by putting the if/else clause on one line, but as you say, that makes it hard to read. This suggests to me that you are trying to do too much work in the Django templates, and that the urls should be constructed else where.

The simplest option is to construct a list of (language_code, url) tags in the view, and loop through these in the template.

{% for lang_code, url in language_urls %}
    <link hreflang={{ lang_code }} href="{{ url }}">
{% endfor %}

If it's not convenient to do this in the view another couple of options are:

  • a template context processor (good if you use the same urls in every view
  • a custom template tag/filter (good if some_path and other_path are dynamic)