gvoysey
gvoysey

Reputation: 546

Jinja2 templates rendering with blanks instead of variables

I'm using jinja2 to generate basic python code for an "app generator" for the framework I'm building.

When rendered and written to a file, jinja2's output contains blanks where the variables ought to be.

I am building a dict of values from a YAML config file

app.pytemplate:

__author__ = {{authorname}}
from plugins.apps.iappplugin import IAppPlugin

class {{appname}}(IAppPlugin):
    pass

YAML:

#basic configuration
appname:  newApp
version:  0.1
repo_url: ''
#author configuration
authorname: 'Foo Bar'
authoremail: ''

generating code (i've snipped some stupid boilerplate arg parsing here)

# read in the YAML, if present.
with open(yamlPath) as _:
configDict = yaml.load(_)

# Make a folder whose name is the app.
appBasePath = path.join(args.output, configDict['appname'])
os.mkdir(appBasePath)

# render the templated app files
env = Environment(loader=FileSystemLoader(templatePath))
for file in os.listdir(templatePath):
    #render it
    template = env.get_template(file)
    retval = template.render(config=configDict)

    if file.endswith(".pytemplate"):
        if file == "app.pytemplate":
            # if the template is the base app, name the new file the name of the new app
            outfile = configDict['appname'] + ".py"
        else:
            #otherwise name it the same as its template with the right extension
            outfile = path.splitext(file)[0] + ".py"
        with open(path.join(appBasePath,outfile),"w") as _:
            _.write(retval)

the YAML is getting parsed correctly (outfile is getting set correctly), but the output is :

__author__ = 
from plugins.apps.iappplugin import IAppPlugin


class (IAppPlugin):
    pass 

What stupid thing am I doing wrong?

Upvotes: 0

Views: 955

Answers (1)

hiro protagonist
hiro protagonist

Reputation: 46859

the yaml module returns a dictionary. there are 2 ways to solve this:

either you keep your template but change the way you pass your dictionary to the render method:

from jinja2 import Template

tmplt = Template('''
__author__ = {{authorname}}
class {{appname}}(IAppPlugin):
''')

yaml_dict = {'authorname': 'The Author',
             'appname': 'TheApp'}

print(tmplt.render(**yaml_dict))

or you pass the dictionary as is to render and change the template:

tmplt = Template('''
__author__ = {{yaml['authorname']}}
class {{yaml['appname']}}(IAppPlugin):
''')

yaml_dict = {'authorname': 'The Author',
             'appname': 'TheApp'}

print(tmplt.render(yaml=yaml_dict))

your jinja2 template accesses the arguments with keywords (as it should). if you just pass the dictionary to the render function you are providing no such keywords.

Upvotes: 2

Related Questions