Flask Webpage Via Cron Job – url_for call broken

Question:

I have a Script that lives in my Flask App that executes every 5 minutes. For many reasons. But that doesn’t matter.

When I run this code I am now wanting to include links in this webpage to functions in my app.py Flask app.

app.py:

@app.route('/Historical-Service-Transitions/<service>')
@login_required
@nocache
def HSPC(service):
    return service

kickoff.py which runs on a schedule.

from jinja2 import Template
import paramiko 
import socket
import time
import pprint
import sys
import mysql.connector
from mysql.connector import errorcode
from collections import namedtuple
import datetime
from app import HSPC
from flask import url_for


source_html =Template(u'''
....#The part that is failing
<tbody>
{% for x in the_best %}
    <tr>
        <td><a href="{{ url_for('HSPC', service ='x.service') }}">{{x.service}}</a></td>
        <td>{{x.ip}}</td>
        <td>{{x.router}}</td>
        <td>{{x.detail}}</td>
        <td>{{x.time}}</td>
    </tr>
{% endfor %}
</tbody>
....''')

full_html = source_html.render(
the_best=the_best,
the_time=the_time
)


write_that_sheet = open("/var/www/flask-intro/templates/Test.html", "w+")
write_that_sheet.write(full_html)
write_that_sheet.close()

Error:

Traceback (most recent call last):
  File "kickoff.py", line 1199, in <module>
    the_time=the_time
  File "/usr/lib/python2.6/site-packages/Jinja2-2.7.3-py2.6.egg/jinja2/environment.py", line 969, in render
    return self.environment.handle_exception(exc_info, True)
  File "/usr/lib/python2.6/site-packages/Jinja2-2.7.3-py2.6.egg/jinja2/environment.py", line 742, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "<template>", line 534, in top-level template code
jinja2.exceptions.UndefinedError: 'url_for' is undefined

Any Help would be much appreciated.


Update:

I am unable to find anything even remotely close to what I am attempting to do. I understand that I can rebuild this so that way the background Python code grabs the info and my app.py builds the HTML. A background application would populate a database, and then a function within the app.py would grab the info needed from the database and post to the HTML Page.

While this is very much last resort as it requires me to redesign this entire part of the application I still would like to see if there is a solution that would allow me to generate a this webpage outside of the app.py Flask.

Asked By: BilliAm

||

Answers:

You are missing the Jinja context that Flask provides. Use flask.render_template_string() to render a template defined in a string and the right template context will be provided for you:

from flask import render_template_string

source_html = u'''
<tbody>
{% for x in the_best %}
    <tr>
        <td><a href="{{ url_for('HSPC', service ='x.service') }}">{{x.service}}</a></td>
        <td>{{x.ip}}</td>
        <td>{{x.router}}</td>
        <td>{{x.detail}}</td>
        <td>{{x.time}}</td>
    </tr>
{% endfor %}
</tbody>
'''

filename = "/var/www/flask-intro/templates/Test.html"

# provide a fake request context for the template
with app.test_request_context('/'), open(filename, "w") as outfh:
    full_html = render_template_string(
        source_html, the_best=the_best, the_time=the_time)
    outfh.write(full_html)

However, for a periodic job, you could just use curl to call a special URL in your Flask app to have it write template output to a file.

Answered By: Martijn Pieters
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.