Tornado/Python self.render("example.html") ignores CSS

12,110

it just generates the html page with no CSS improving its appearance even though I've placed my .css file along with the example.html page in the same folder "Tornado/template". Pretty sure I got that link html to css tag right as well.

The css belongs into the static folder, that you have declared here:

"static_path": os.path.join(config.base_dir, "static")

This is how to link it into the template:

<link rel="stylesheet" href="{{ static_url("presnt.css") }}">
Share:
12,110
TK Tang
Author by

TK Tang

2017: Final year student for Software Engineering at University of Sydney. I like developing web applications using Spring framework although I'm rather novice at it. 2019: .NET, NodeJS, ReactJS, NG developer

Updated on July 26, 2022

Comments

  • TK Tang
    TK Tang almost 2 years

    I'm a novice in Python and programming in general. I use a web server called Tornado to "host" my websites. Whenever I use self.render("example.html", variables here) to generate a dynamic html page, the html page produced has no CSS incorporated into it, as in it just generates the html page with no CSS improving its appearance even though I've placed my .css file along with the example.html page in the same folder "Tornado/template". Pretty sure I got that link html to css tag right as well.

    If I open example.html with browser and not with Tornado, it will "render" with the .css file.

    Since I don't know why this is happening, I'll just post all my code here: This is the app.py in Tornado:

    import config
    import os.path
    import re
    import MySQLdb
    import tornado.ioloop
    import tornado.web
    
    
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.render("question3.html")
    
    class StopTornado(tornado.web.RequestHandler):
        def get(self):
            tornado.ioloop.IOLoop.instance().stop()
    
    class ReturnQuery(tornado.web.RequestHandler):
        def post(self):
    
            connection = MySQLdb.connect(**config.mysql_config)
            cursor = connection.cursor()
    
            if 'lowermass' in self.request.arguments and 'uppermass' in self.request.arguments:
                lowermass = self.get_argument('lowermass')
                uppermass = self.get_argument('uppermass')
                # Testing for bad input and should block Injection attacks
                # Since you can't really do an injection attack with only numbers
                # Placing any non-int input will throw an exception and kick you to the      Error.html page
                try:
                    lowermass = int(lowermass)
                    uppermass = int(uppermass)
                except ValueError:
                    self.render("Error.html")
                if lowermass < uppermass:
    
                    cursor.execute ('''SET @row_num=0;''')
                    cursor.execute('''SELECT @row_num:=@row_num+1 as 'Num', b.commonname
                                    FROM Bird b
                                    JOIN Bodymass m ON b.EOLid = m.EOLid
                                    WHERE m.mass BETWEEN %s AND %s
                                    GROUP BY b.commonname''',(lowermass, uppermass))
    
                    birds = cursor.fetchall()
                    self.render("question2.html", birds = birds)
                else:
                    self.render("Error.html")
    
            else :
                self.render("Error.html")
    
    class Application(tornado.web.Application):
        def __init__(self):
            handlers = [
                (r"/", MainHandler),
                # Add more paths here
                (r"/KillTornado/", StopTornado),
                (r"/tables/", ReturnQuery),
                (r"/tables/localhost8888", MainHandler)
            ]
            settings = {
                "debug": True,
                "template_path": os.path.join(config.base_dir, "templates"),
                "static_path": os.path.join(config.base_dir, "static")
            }
            tornado.web.Application.__init__(self, handlers, **settings)
    
    if __name__ == "__main__":
        app = Application()
        app.listen(config.port)
        print "Starting tornado server on port %d" % (config.port)
        tornado.ioloop.IOLoop.instance().start()
    

    And this is the html page that I'm trying to render:

    So basically, I receive two integer input from a different html page from a web user and a mysql query is performed the app.py above on a database. It returns a list (I think it's a list of lists) of all the results and I use the data to fill in a table in the html page below but it's the html page containing the table that won't get "rendered" with css.

    lowermass and uppermass is the user inputs (must be int). question3.html is the html page to get the user input and question2.html is the html page with the table.

    I seriously hope it's just a dumb mistake I can quickly fix.

    <html>
    <head>
    <link rel = "stylesheet" type ="text/css" href = "presnt.css">
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.min.js"></script>
    <script src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
    <script>
    $(document).ready(function(){
    $('#table').dataTable();
    });
    </script>
    
    
        <title>Birds with body mass in range</title>
            <div id = "header">
            Birds with body mass in range
            </div>
            <br>
    </head>
    <body>
        <table id = "table">    
            <thead>
                    <tr>
                    <td style="padding:4px;border-top:1px solid black;">rownum</td>
                    <td style="padding:4px;border-top:1px solid black;">common name</td>  
                    </tr>
                     <tr>
                    <td style = "padding:1px;border-top:1px solid black;">
                    </td>
                    <td style = "padding:1px;border-top:1px solid black;">
                    </td>
                </tr>
            </thead>
            <tbody>
                {% if birds %}
                {% for bird in birds %}
                <tr>   
                    <td>{{ bird[0] }} </td>
                    <td>{{ bird[1] }}</td>   
                </tr>
                {% end %}
                {% else %}
                <tr>
                    <td colspan = 2> No results returned</td>
                </tr>
                {% end %}
            </tbody>
        </table>  
    </body>
    

  • TK Tang
    TK Tang almost 10 years
    It didn't work :( - I put the presnt.css in Tornado/Static/css and the html page I have is in Tornado/Template and I edited the html css link thing to exactly what you wrote. Saved, restarted Tornado. And to be honest - I don't know what this : ""static_path": os.path.join(config.base_dir, "static")" means. It was already there when I opened app.py
  • TK Tang
    TK Tang almost 10 years
    NEVERMIND - I fixed it. Thank you sooo much though, your answer got me thinking. Since app.py was in "/Tornado" and I had my presnt.css file placed in "/Tornado/Static/css" directory, I just needed to grab that link and put it in the href with "presnt.css" at the end of course. I couldn't solve such a simple problem looooool - I should probably switch out of software engineering to an Arts degree, something like that taking an hour for me to figure out would surely get me fired in the industry.