What is the Flask version of Django's render_to_string function?
Question:
So, I’m trying to learn TDD for Flask, by translating this code to Flask. I’ve been trying to find how to render a template to a string for a while now. Here is what I have tried:
render_template(...)
render_template_string(...)
make_response(render_template(...)).data
and none of them seem to work.
The error in each case seems to be
"...templating.py", line 126, in render_template
ctx.app.update_template_context(context)
AttributeError: 'NoneType' object has no attribute 'app'
in templating.py
‘s render_template
function.
My test code is as follows:
def test_home_page_can_save_POST_request(self):
with lists.app.test_client() as c:
c.get('/')
rv = c.post('/', data = {'item_text':"A new list item"})
# This test works
self.assertIn("A new list item", rv.data)
# This test doesn't
self.assertEqual(rv.data,flask.make_response(flask.render_template('home.html',new_item_text='A new list item')).data)
with home.html
as follows:
<html>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />
</form>
<table id="id_list_table">
<tr><td>{{ new_item_text }}</td></tr>
</table>
</body>
</html>
Edit: I’ve added more files, because the error may be unrelated to the actual function used. I’m using exactly what Celeo has suggested in his answer.
Answers:
You’re on the right path with make_response
:
response = make_response(render_template_string('<h2>{{ message }}</h2>', message='hello world'))
Then,
response.data
is
<h2>hello world</h2>
That response
object is documented here.
Celeo is correct, but there are two additional things to consider (one of which is peculiar to the render_template function):
First, it looks like you have an indentation problem in your revised function. It looks like you’re calling rv.data outside of the “with” statement. The “assertEqual” statement should be within the same block/indentation-level as the “assertIn” statement. (It looks like you’ve placed it outside of the block at the moment.)
Second — and more importantly — the render_template function in flask adds newline characters at the beginning and end of the outputted HTML. (You can verify this from the python interactive shell by printing the following command to stdout:
flask.render_template('home.html',new_item_text='A new list item').data # adds 'n' at start & end
The output you’ll get will have newline characters (“n”) at the beginning and end of the output.
Therefore, you should try stripping the output with the strip() function as shown below:
def test_home_page_can_save_POST_request(self):
with lists.app.test_client() as c:
c.get('/')
rv = c.post('/', data = {'item_text':"A new list item"})
self.assertIn("A new list item", rv.data)
# Suggested Revision
self.assertEqual(rv.data,flask.make_response(flask.render_template('home.html',new_item_text='A new list item')).data.strip())
That should hopefully do the trick.
So, I’m trying to learn TDD for Flask, by translating this code to Flask. I’ve been trying to find how to render a template to a string for a while now. Here is what I have tried:
render_template(...)
render_template_string(...)
make_response(render_template(...)).data
and none of them seem to work.
The error in each case seems to be
"...templating.py", line 126, in render_template
ctx.app.update_template_context(context)
AttributeError: 'NoneType' object has no attribute 'app'
in templating.py
‘s render_template
function.
My test code is as follows:
def test_home_page_can_save_POST_request(self):
with lists.app.test_client() as c:
c.get('/')
rv = c.post('/', data = {'item_text':"A new list item"})
# This test works
self.assertIn("A new list item", rv.data)
# This test doesn't
self.assertEqual(rv.data,flask.make_response(flask.render_template('home.html',new_item_text='A new list item')).data)
with home.html
as follows:
<html>
<body>
<h1>Your To-Do list</h1>
<form method="POST">
<input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />
</form>
<table id="id_list_table">
<tr><td>{{ new_item_text }}</td></tr>
</table>
</body>
</html>
Edit: I’ve added more files, because the error may be unrelated to the actual function used. I’m using exactly what Celeo has suggested in his answer.
You’re on the right path with make_response
:
response = make_response(render_template_string('<h2>{{ message }}</h2>', message='hello world'))
Then,
response.data
is
<h2>hello world</h2>
That response
object is documented here.
Celeo is correct, but there are two additional things to consider (one of which is peculiar to the render_template function):
First, it looks like you have an indentation problem in your revised function. It looks like you’re calling rv.data outside of the “with” statement. The “assertEqual” statement should be within the same block/indentation-level as the “assertIn” statement. (It looks like you’ve placed it outside of the block at the moment.)
Second — and more importantly — the render_template function in flask adds newline characters at the beginning and end of the outputted HTML. (You can verify this from the python interactive shell by printing the following command to stdout:
flask.render_template('home.html',new_item_text='A new list item').data # adds 'n' at start & end
The output you’ll get will have newline characters (“n”) at the beginning and end of the output.
Therefore, you should try stripping the output with the strip() function as shown below:
def test_home_page_can_save_POST_request(self):
with lists.app.test_client() as c:
c.get('/')
rv = c.post('/', data = {'item_text':"A new list item"})
self.assertIn("A new list item", rv.data)
# Suggested Revision
self.assertEqual(rv.data,flask.make_response(flask.render_template('home.html',new_item_text='A new list item')).data.strip())
That should hopefully do the trick.