spritecodej
spritecodej

Reputation: 459

python tornado json render to html script

I want to render json file to html script part. In the tornado part, No1 is sendering json data to html. And, No2 part is received the json data from No1. However this code is not working. I found that html script doesn't allow the form of {{ }}. How I send the json data to part of html ?

[ python - tornado part ]

import tornado.web
import tornado.httpserver
import tornado.ioloop
import os.path
from tornado.options import define, options
define("port", default=3000, help="run on the given port", type=int)

class Application(tornado.web.Application):
    def __init__(self):
        base_dir = os.path.dirname(__file__)
        settings = {
        }
        tornado.web.Application.__init__(self, [
            tornado.web.url(r"/", MainHandler, name="main"),
        ], **settings)

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        data = {"name":"John Johnson","street":"Oslo West 16","phone":"555 1234567"}

        self.render("index.html", data=data)                        #No1

def main():
    tornado.options.parse_command_line()
    Application().listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

[ html part ]

<!DOCTYPE html>
<html>
<body>
<h2>JSON Object Creation in JavaScript</h2>
<p id="demo"></p>
<script>
/* var text = '{"name":"John Johnson","street":"Oslo West 16","phone":"555 1234567"}'; */

var text = '{{data}}';                                          /*No2*/
var obj = JSON.parse(text);

document.getElementById("demo").innerHTML =
obj.name + "<br>" +
obj.street + "<br>" +
obj.phone;
</script>

</body>
</html>

Upvotes: 2

Views: 4259

Answers (2)

Loy
Loy

Reputation: 31

The key point is that string will be autoescaped by template engine. So we need to decode it before parsing it as a json.

{% raw %} directive mentioned by @clockwatcher is one solution. But it may cause error if the variable text is double-quoted since json.dumps(data) will use double quotation marks in its output.

Therefore, a possible better solution is to unescape text.

import tornado.web
import tornado.httpserver
import tornado.ioloop
import os.path
import json
from tornado.options import define, options

define("port", default=3000, help="run on the given port", type=int)

class Application(tornado.web.Application):
    def __init__(self):
        base_dir = os.path.dirname(__file__)
        settings = {
        }
        tornado.web.Application.__init__(self, [
            tornado.web.url(r"/", MainHandler, name="main"),
        ], **settings)

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        data = {"name":"John Johnson","street":"Oslo West 16","phone":"555 1234567"}
        self.render("index.html", data=json.dumps(data))

def main():
    tornado.options.parse_command_line()
    Application().listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()
<!DOCTYPE html>
<html>
  <body>
    <h2>JSON Object Creation in JavaScript</h2>
    <p id="demo"></p>
    <script>
      String.prototype.unescapeHtml = function () {
          var temp = document.createElement("div");
          temp.innerHTML = this;
          var result = temp.childNodes[0].nodeValue;
          temp.removeChild(temp.firstChild);
          return result;
      }

      var text = '{{data}}';
      var obj = JSON.parse(text.unescapeHtml());

      document.getElementById("demo").innerHTML =
          obj.name + "<br>" +
          obj.street + "<br>" +
          obj.phone;
    </script>
  </body>
</html>

The snippet of function unescapeHTML comes from JavaScript: how to unescape HTML entities.

Upvotes: 3

clockwatcher
clockwatcher

Reputation: 3373

The {{ }} in your index.html template will be autoescaped for html. You want raw output because in this case you're outputting javascript rather than html. You also want to make sure you're actually letting python convert your data object to correctly formatted json.

Import the json library and add a call to json.dumps to get correctly formatted JSON:

import tornado.web
import tornado.httpserver
import tornado.ioloop
import os.path
import json

from tornado.options import define, options
define("port", default=3000, help="run on the given port", type=int)

class Application(tornado.web.Application):
    def __init__(self):
        base_dir = os.path.dirname(__file__)
        settings = {
        }
        tornado.web.Application.__init__(self, [
            tornado.web.url(r"/", MainHandler, name="main"),
        ], **settings)

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        data = {"name":"John Johnson","street":"Oslo West 16","phone":"555 1234567"}

        self.render("index.html", data=json.dumps(data))

def main():
    tornado.options.parse_command_line()
    Application().listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

And use raw to prevent the html auto-escaping output in your template:

<!DOCTYPE html>
<html>
<body>
<h2>JSON Object Creation in JavaScript</h2>
<p id="demo"></p>
<script>
/* var text = '{"name":"John Johnson","street":"Oslo West 16","phone":"555 1234567"}'; */

var text = '{% raw data %}';
var obj = JSON.parse(text);

document.getElementById("demo").innerHTML =
obj.name + "<br>" +
obj.street + "<br>" +
obj.phone;
</script>
<body>
</body>
</html>

Upvotes: 5

Related Questions