niwinz / django-jinja

Simple and nonobstructive jinja2 integration with Django.
http://niwinz.github.io/django-jinja/latest/
BSD 3-Clause "New" or "Revised" License
363 stars 102 forks source link

allow for backslashes in template_name on windows #249

Closed wizpig64 closed 4 years ago

wizpig64 commented 4 years ago

This pull request fixes finding template paths with backslashes in windows environments.

While I use linux to build and run my django project, I recently did some work getting it to run on windows, so that other non-posix people in my office could contribute. Having this change in place would have saved me a lot of time tracing through callstacks, so I figured I would share it.

It is common to see code on the internet encouraging the use of os.path.join() for creating paths to django templates, as the django template engine works with whatever slashes the OS uses. Jinja2, on the other hand, will only work with forward-slash style paths.

Due to the way Django will move on to the next available template engine if ours gives a TemplateNotFound error, it does not do a very good job at surfacing this kind of mistake, instead passing the template to the django template engine, and failing with a syntax error.

Rather than creating more work for django-jinja users ("be sure to use os.path.join everywhere you use django templates, and posixpath.join everywhere you use jinja templates!"), this pull request just fixes these backslash paths when django-jinja can't find a template in windows, and tries again.


If this change is deemed out of scope (as we don't really advertise or test windows support), or is otherwise rejected, readers can feel free to use this shim I wrote to get my project to work on windows, and I'll leave it at that:

from django_jinja.backend import Jinja2

class Jinja2Backslasher(Jinja2):
    """Transforms template_name backslashes for Windows compatibility."""

    def get_template(self, template_name):
        # example: 'path/to\\some.jinja' -> 'path/to/some.jinja'
        template_name = template_name.replace("\\", "/")
        return super(Jinja2Backslasher, self).get_template(template_name)

Then, in settings.py, change the backend here from "django_jinja.backend.Jinja2":

TEMPLATES = [
    {
        "BACKEND": "your.project.Jinja2Backslasher",
        "NAME": "jinja2",