Reputation: 30985
Is it possible to access a OS environment variable directly from a Jinja2 template?
Upvotes: 29
Views: 47744
Reputation: 1
The top answer parses env vars in the following format:
my_secret: "{{ 'default value' | env('ENV_VAR') }}"
I noticed other tools such as DBT use another format, such as:
my_secret: "{{ env('ENV_VAR', 'default value') }}"
I managed to implement a solution similar to the top answer by rendering the env function as a template variable and passing the args to os.getenv in a lambda function:
import os
import yaml
from jinja2 import Environment
def read_yaml_with_env(yaml_str: str) -> dict:
# Apply Jinja Template and load environment variables
env = Environment()
template = env.from_string(yaml_str)
yaml_vars = template.render(env=lambda x, y: os.getenv(x, y))
# Load YAML
json_from_yaml = yaml.safe_load(yaml_vars)
return json_from_yaml
Upvotes: 0
Reputation: 9265
My simplest solution for FastAPI
templates.env.globals.update(getenv=os.getenv)
In Jinja2
{{ getenv("FOO") }}
Upvotes: 0
Reputation: 1629
Here is a list of variables that you can access from your template.
I was trying to access some app.config
variables and I managed to do it by calling config
:
{% if current_user.id == config['ADMIN_ID'] %}
######## SOME HTML ########
{% endif %}
Flask-Login adds the current_user
variable to your templates
Upvotes: 0
Reputation: 483
In bash let's setup our example
export MYENVVAR=foo
$ nano example.py
from jinja2 import Template
import os
template = Template("Hello {{ env['MYENVVAR'] or 'DefaultVal' }}")
r = template.render(env=os.environ, name='somethingelse')
print(r)
Run template
$ python3 example.py
https://jinja.palletsprojects.com/en/2.11.x/intro/
Upvotes: 4
Reputation: 30985
Following @Renier's pointer about custom filters in the comments, I figured out a possible solution.
Define a custom filter:
def env_override(value, key):
return os.getenv(key, value)
Install the filter in the environment:
env.filters['env_override'] = env_override
Use the filter as follows:
"test" : {{ "default" | env_override('CUSTOM') }}
Where the appropriate environment variable can be set as:
export CUSTOM=some_value
If the environment variable is set the output will be:
"test" : some_value
Otherwise:
"test" : default
Upvotes: 20
Reputation: 1715
The answer here works beautifully but you can still get rid of the useless use of cat and compress it to a single statement:
python -c 'import os
import sys
import jinja2
sys.stdout.write(
jinja2.Template(sys.stdin.read()
).render(env=os.environ))' <$CONFIGTEMPLATE >$CONFIGFILE
P.S.: Stack Overflow does not allow formatted code in comments. Therefore I had to post this as a separate answer instead of commenting on https://stackoverflow.com/a/27984610/1070890.
Upvotes: 12
Reputation: 16416
I believe you can access environment variables like so:
{{ env['XMPP_DOMAIN'] or "localhost" }}
This is from an example in a config file that I saw recently for a Docker deployment of ejabberd.
hosts:
- "{{ env['XMPP_DOMAIN'] or "localhost" }}"
NOTE: You can see the rest of the example in the run file from the Github repo.
As I understand things the heavy lifting is done by this bit of code:
readonly PYTHON_JINJA2="import os;
import sys;
import jinja2;
sys.stdout.write(
jinja2.Template
(sys.stdin.read()
).render(env=os.environ))
"""
And this code is what is used to generate a template file:
cat ${CONFIGTEMPLATE} \
| python -c "${PYTHON_JINJA2}" \
> ${CONFIGFILE}
Upvotes: 10