patternpythonMinor
Jinja2 template loader
Viewed 0 times
loadertemplatejinja2
Problem
I am playing around with building my own back end with python 2.7 and jinja2/cgi. Originally I was defining some of my environment and loader variables at the top but figured this was not the best practice. I then defined functions for each, but they'd only get called once or twice depending on which route it decided to execute. I came up with this class idea instead that I pass into my dispatch function, which in turn passes it into whatever rendering function happens to be being executed. Is this the proper 'pythonic' way to approach having a template loader, and if not would anyone have any suggestions?
This class then allows me to just call
class Template(object):
def __init__(self):
self._environment = None
def __call__(self, temp_name):
return self.get_env.get_template(temp_name)
@property
def get_env(self):
return self._environment
@get_env.getter
def get_env(self):
if not self._environment:
self._loader = jinja2.FileSystemLoader(searchpath=os.path.join(
os.path.dirname(os.path.abspath(__file__)), '../templates/madlib/'))
self._environment = jinja2.Environment(loader = self._loader)
return self._environmentThis class then allows me to just call
template('templateFileName.j2') and be returned that jinja template object. If the environment is not created, the getter will create one for me.Solution
For starter, I'd rewrite
Next I would cleanup your
Lastly, since the initialization of
This way,
So now, no need to pass an object around everywhere, just call the function when you need to.
And if you want to, EAFP can also help reduce the overhead of the
get_env a bit and introduce intermediate variables for readability:def get_env(self):
if not self._environment:
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
self._environment = jinja2.Environment(loader=loader)
return self._environmentNext I would cleanup your
@property usage; since the raw decorator already defines the getter property, you can get rid of the first method:class Template(object):
def __init__(self):
self._environment = None
def __call__(self, temp_name):
return self.get_env.get_template(temp_name)
@property
def get_env(self):
if not self._environment:
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
self._environment = jinja2.Environment(loader=loader)
return self._environmentLastly, since the initialization of
_environment is meant to be done (and thus checked) only once, why not take advantage of attribute access that already offer us this kind of flexibility:class Template(object):
def __call__(self, temp_name):
return self.environment.get_template(temp_name)
def __getattr__(self, attribute):
if attribute == 'environment':
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
self.environment = env = jinja2.Environment(loader=loader)
return env
return super(Template, self).__getattr__(attribute)This way,
__getattr__ is only called the first time self.environment is accessed and never again. But... Hold on... The only usefull method of this class is __call__... Better write a function instead; this will bring the check back at each call but will make the intent clearer:def load_template(template_name):
if not hasattr(load_template, 'environment'):
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
load_template.environment = jinja2.Environment(loader=loader)
return load_template.environment.get_template(template_name)So now, no need to pass an object around everywhere, just call the function when you need to.
And if you want to, EAFP can also help reduce the overhead of the
hasattr test:def load_template(template_name):
try:
environment = load_template.environment
except AttributeError:
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
load_template.environment = environment = jinja2.Environment(loader=loader)
return environment.get_template(template_name)Code Snippets
def get_env(self):
if not self._environment:
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
self._environment = jinja2.Environment(loader=loader)
return self._environmentclass Template(object):
def __init__(self):
self._environment = None
def __call__(self, temp_name):
return self.get_env.get_template(temp_name)
@property
def get_env(self):
if not self._environment:
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
self._environment = jinja2.Environment(loader=loader)
return self._environmentclass Template(object):
def __call__(self, temp_name):
return self.environment.get_template(temp_name)
def __getattr__(self, attribute):
if attribute == 'environment':
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
self.environment = env = jinja2.Environment(loader=loader)
return env
return super(Template, self).__getattr__(attribute)def load_template(template_name):
if not hasattr(load_template, 'environment'):
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
load_template.environment = jinja2.Environment(loader=loader)
return load_template.environment.get_template(template_name)def load_template(template_name):
try:
environment = load_template.environment
except AttributeError:
cwd = os.path.dirname(os.path.abspath(__file__))
madlib_dir = os.path.join(cwd, '..', 'templates', 'madlib')
loader = jinja2.FileSystemLoader(searchpath=madlib_dir)
load_template.environment = environment = jinja2.Environment(loader=loader)
return environment.get_template(template_name)Context
StackExchange Code Review Q#157058, answer score: 2
Revisions (0)
No revisions yet.