Q:

Windows line breaks in plain text rendered using Django template

I am attempting to export data to a plain text file using Django 1.10 (Python 3.5) views/templates.  This text file must be OS agnostic in that Windows users ought to have no trouble viewing the file. Unfortunately, when Django renders my template which has \r\n (Windows friendly) line breaks in the file, the line breaks are magically converted into \n (Mac/Linux friendly) line breaks.  What gives?
Here's how I'm attempting to render the plain text file:
from django.template import loader, Context

def myview(request):
    my_data = get_my_data()
    response = HttpResponse(content_type='text/plain')
    response['Content-Disposition'] = 'attachment; filename="export.txt"'
    template = loader.get_template('export.txt') # <- this file has \r\n line breaks
    context = Context({'data': my_data})
    response.write(template.render(context))

    return response

Upon downloading the exported file using Chrome or Edge in Windows and opening in Notepad, the line breaks aren't respected, and upon viewing the file in Notepad++ (and showing EOL characters), only the \n character is there! Any help would be greatly appreciated :)

A:

I have faced the same issue, unfortunately this seems to happen in Django's template loader/engine somewhere. If you initiate a Template directly without going through get_template() (or render_to_string() and similar methods which uses the same calls), this does not happen. Here is a simplified version of my testcase:
>>> from django import template
>>> t = template.Template('{% for line in dataset %}{{ line.field1 }}\t{{ line.field2 }}\r\n{{ line.field3 }}\t{{ line.field4 }}\r\n{% endfor %}')
>>> dataset = {'field1': 'F1', 'field2': 'F2', 'field3': 'F3', 'field4': 'F4'}
>>> c = template.Context({'dataset': dataset})
>>> t.render(c)

This outputs the template correctly with \r\n in place:
u'F1\tF2\r\nF3\tF4\r\n'

However if I load the same template from a file, using get_template() like you do, it strips them:
>>> from django.template import loader
>>> t = loader.get_template('test.txt')
>>> t.render(c)
u'F1\tF2\nF3\tF4\n'

I tried wading through the Django code in order to identify where this occurs, but with time constraints on my hand I  ended up doing the "quick'n'dirty" fix instead:
>>> t = loader.get_template('test.txt')
>>> out = t.render(c).replace('\n', '\r\n')

Beware, this replaces any \n you might have in the actual data fields too, so use with caution....

