How can I load Jinja2 templates dynamically from Google Cloud Storage in App Engine?
How can I load Jinja2 templates dynamically from Google Cloud Storage in App Engine?
I have an application on App Engine and want to deploy my Jinja2 templates in a way that lets me dynamically update them without needing to redeploy my entire application.
Ideally they would be stored in Google Cloud Storage, which would allow me to just replace the template files in a bucket and have them be immediately used by the live application. However, Flask seems to require the templates to be local to the application.
Is this at all possible?
2 Answers
2
This would be possible by loading each template directly from Google Cloud Storage for every request, and using the render_template_string function from Flask.
render_template_string
For example, if your template file hello.html looks like this:
hello.html
<h1>Hello name !</h1>
Add the Google Cloud Storage resource to your application, create a new bucket (let's call it your-bucket), and upload this file to the bucket.
your-bucket
In your requirements.txt:
requirements.txt
flask
google-cloud-storage
In your main.py:
main.py
from flask import Flask, render_template_string
from google.cloud import storage
app = Flask(__name__)
# Initialize the bucket you created containing the templates
bucket = storage.Client().bucket('your-bucket')
@app.route('/')
def hello():
# Load the template string from Cloud Storage
template_string = bucket.blob('hello.html').download_as_string().decode('ascii')
# Now use render_template_string the same way you'd use render_template
return render_template_string(template_string, name='World')
Note that since this application would re-download the template for every request, for high-traffic applications it would possibly incur significant additional request time, as well as cost.
Due to this, it would be ideal to "cache" the template string in some way (for example, via Cloud Memorystore), and then use an Object Change Notification (possibly via a Google Cloud Function trigger) to determine when the file has changed in the bucket, and update the cache.
Here's a nice wrapper of the Flask render_template() call to achieve this that either
You can then copy your /templates file to your Google CDN and reference the public URL
-
from flask import Flask, render_template, render_template_string
def renderTemplateLocalOrRemote(file, **kwargs):
if REMOTE_LOADING_ENABLED is defined: # Load the template file remotely
r = requests.get('https://'+YOUR_BASE_URL+"/templates/"+file)
template_string = r.content.decode('utf-8')
return render_template_string(template_string, **kwargs)
else: # Load the template file from local, pass on to standard method
return render_template(file, **kwargs)
You can then use this wrapper everywhere you were using flask.render_template()
@app.route('/')
def hello():
return renderTemplateLocalOrRemote('hello.html', name='lalala', another_param='lilili')
@app.route('/another_route')
def hello2():
return renderTemplateLocalOrRemote('hello2.html', different_param='lilili')
and toggle it on/off using
REMOTE_LOADING_ENABLED
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You can develop your own Jinja template loader to load templates from a different source. But your "immediately used by the live application" is not that easy because templates are cached.
– voscausa
Sep 5 '18 at 19:23