Disable template processing in Tornadoweb

All we need is an easy explanation of the problem, so here it is.

I have to use Tornadoweb as RESTfull backend for our existing AngularJs application.

The {{}} are heavily used in the angular app. I would like to serve angular files from tornado as static files

Is there a way to disable processing templates by tornado to avoid conflicts with {{}} used by tornado?

I know how to change the {{}} in the angular app with $interpolateProvider but it will involve a lot of changes in the angular app.

As a temporary solution, I put the angular app in the static folder of tornado and used a redirect:

class IndexHandler(RequestHandler):
    def get(self):
        self.redirect(self.static_url('ng-app/index.html'),True)

It is working but it is not a nice solution because The url displayed is some thing like :

http://localhost:8080/static/ng-app/index.html?v=efb937e6a0cb0739eb0edfd88cfb4844

Any better idea?

Thank you in advance

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Use {{!tag}} to disable the translation of tornado.

Method 2

You can use Tornado’s built in StaticFileHandler. This passes everything as static files to Angular:

from tornado import options, ioloop, web

options.define("port", default=8888, help="run on the given port", type=int)

SETTINGS = {
    "debug" : True
}

application = web.Application([
    (r'/(.*)', web.StaticFileHandler, {"path": "angular_app"})
],**SETTINGS)


if __name__ == "__main__":
    options.parse_command_line()
    application.listen(options.options.port)
    ioloop.IOLoop.instance().start()

Method 3

Tricky and quite ugly solution: you can just use self.write() instead of self.render() to print contents of file. If it’s a HTML page, then there will be more GET requests for .css, .js files and images so you have to have second handler to return them all. Example for AngularJS application from: http://architects.dzone.com/articles/angularjs-get-first-impression

Project tree:

$ tree
.
├── angular_app
│   ├── css
│   │   ├── app.css
│   │   └── bootstrap.css
│   ├── img
│   │   └── ajax-loader.gif
│   ├── index.html
│   └── js
│       ├── app.js
│       ├── contollers
│       │   └── CurrencyConvertCtrl.js
│       ├── db.js
│       ├── models
│       │   └── Currency.js
│       ├── _references.js
│       └── vendor
│           ├── angular.js
│           ├── bootstrap.js
│           ├── highcharts.js
│           └── jquery-1.9.1.js
├── test.py
└── test.py~

Tornado code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

import logging

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

import os 
angular_app_path=os.path.join(os.path.dirname(__file__), "angular_app")

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        with open(angular_app_path + "/index.html", 'r') as file:
            self.write(file.read())     

class StaticHandler(tornado.web.RequestHandler):
    def get(self): 
        self.set_header('Content-Type', '') # I have to set this header
        with open(angular_app_path + self.request.uri, 'r') as file:
            self.write(file.read())

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(
    handlers=[(r'/', IndexHandler), (r'/js.*', StaticHandler), (r'/cs.*', StaticHandler), (r'/img.*', StaticHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

Method 4

dumb way:

just use:

self.render('some-template.html', var1='{{var1}}') 

since {{var1}} the template removes first the {{ }} and then replaces the var1 so the result will be {{var1}} in the rendered html file 😉

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply