mcfmk
mcfmk

Reputation: 53

Jinja2 {% include file %} outside of search path doesn't work

This is an elementary issue which is probably related to Jinja2 PrefixLoader or ChoiceLoader.

On Python 3.6 we load with this command

jinja2.FileSystemLoader( searchpath= "\\template_folder\\")

On Windows 7, our file structure is as follows.

- folder_bbb
    * subfile.txt
- template_folder
     * template_file
     - folder_aaa
         * subfile.txt

From the template_file we are successful with this command

{% include "folder_aaa/subfile.txt" %} 

Now we wish to move the file one level up, and write

{% include "../folder_bbb/subfile.txt" %}

but that doesn't work, complaining file not found.

What is the correct way to write? Thanks.

Upvotes: 5

Views: 5489

Answers (2)

Solmyr87
Solmyr87

Reputation: 11

I had this exact issue and spent a whole day going crazy over it before realizing that Jinja2’s FileSystemLoader sets the root directory based on the template being loaded.

When you define FileSystemLoader(searchpath="\\template_folder\\"), template_folder becomes the root directory for all templates. This means:

  • {% include "folder_aaa/subfile.txt" %} works because "folder_aaa" is inside "template_folder".

  • {% include "../folder_bbb/subfile.txt" %} does not work because folder_bbb is outside of template_folder, and FileSystemLoader can’t navigate upwards in the filesystem.

Solution 1: Modify FileSystemLoader to include multiple paths

If you have control over the loader, you can specify multiple search paths so that both template_folder and folder_bbb are included:

jinja2.FileSystemLoader(["c:\\template_folder\\", "c:\\folder_bbb\\"])

Now, you can just do:

{% include "subfile.txt" %}

and Jinja2 will search for the file in both directories.

Solution 2: If you cannot modify FileSystemLoader (e.g., in Ansible or another environment)

Then you’re stuck with relative paths inside the root directory, meaning you can only include files downwards.

In my case (while working with Ansible), the solution was to move the template I was loading to the highest level (template_folder). That way, I could reference included templates using downward relative paths instead of trying to include files from a parent directory.

Upvotes: 0

uǝM ƃuǝℲ 馮文
uǝM ƃuǝℲ 馮文

Reputation: 123

You may specify all paths in the the loader

jinja2.FileSystemLoader(["c:\\template_folder\\", "c:\\folder_bbb\\"])

and refer the including block without a specific path

{% include "subfile.txt" %} 

The path will be searched in order so that as you say, moving the file one level up, the file will be found. (You need the template_folder path for the template itself.)

Upvotes: 5

Related Questions