4

Not a very experienced user with python here, just picked up python while staying at home. I was looking into integrating the output of flask-table to a website. The following is my python code that creates a simple table for my website.

    from flask_table import Table, Col

    app = Flask(__name__)

    class ItemTable(Table):
        name = Col('Name')
        description = Col('Description')

    Class Item(object):
        def __init__(self, name, description):
            self.name = name
            self.description = description

    items = [dict(name='Name1', description='Description1'),
             dict(name='Name2', description='Description2'),
             dict(name='Name3', description='Description3')]

    table = ItemTable(items)


    @app.route("/")
    def hello():
        return render_template('index.html', tStrToLoad=table.__html__())

    if __name__ == "__main__":
        app.run()

and my html code that takes tStrToLoad from the python code above to display.

<html>
    <head>
        <title>Test Flask Table</title>
        <style>
            body 
            {
                background-color: #000000;
                color: #FFFFFF;
                font-family:Verdana;
                font-size:16px;
            }
            table, th, td
            {
                border: 1px solid #0088ff;
                border-collapse: collapse;
                padding: 3px;
                font-family:Verdana;
                font-size:12px;
                text-align: left;
            }

        </style>
    </head>
    <body>
        a simple test table
        <br/><br/>

        {{ tStrToLoad }}

    </body>
</html>

And instead of showing a table with the data, I have the following output in a black background

a simple test table

<table> <thead><tr><th>Name</th><th>Description</th></tr></thead> <tbody> <tr><td>Name1</td><td>Description1</td></tr> <tr><td>Name2</td><td>Description2</td></tr> <tr><td>Name3</td><td>Description3</td></tr> </tbody> </table>

Upon further investigating, I did a view page source, this is my actual html code that arises from this.

<html>
    <head>
        <title>Test Flask Table</title>
        <style>
            body 
            {
                background-color: #000000;
                color: #FFFFFF;
                font-family:Verdana;
                font-size:16px;
            }
            table, th, td
            {
                border: 1px solid #0088ff;
                border-collapse: collapse;
                padding: 3px;
                font-family:Verdana;
                font-size:12px;
                text-align: left;
            }

        </style>
    </head>
    <body>
        a simple test table
        <br/><br/>

        &lt;table&gt;
&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Name1&lt;/td&gt;&lt;td&gt;Description1&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Name2&lt;/td&gt;&lt;td&gt;Description2&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Name3&lt;/td&gt;&lt;td&gt;Description3&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

    </body>
</html>

My question is how do I format it correctly in my python script such that it sends < and > instead of & lt; and & gt;

Rascal
  • 43
  • 1
  • 5

1 Answers1

7

If you're confident none of the data in the table has un-validated user input then tell Jinja not to escape the html:

{{ tStrToLoad | safe }}

However you may wish to avoid using Flask-tables, and just pass the items list yourself. The template code can become more generic if you also pass some headers in a separate list:

        headers = ['Name','Description']
        return render_template('index.html',
                               headers = headers,
                               objects = items)

Then manually build the table:

{% if objects %}
  <table id='result' class='display'>
    <thead>
      <tr>
      {% for header in headers %}
        <th>{{header}}</th>
      {% endfor %}
      </tr>
    </thead>

    <tbody>
    {% for object in objects %} 
      <tr>
    {% for k, val in object.items() %}
        <td>{{val}}</td>
      {% endfor %}
      </tr>
    {% endfor %}        
    </tbody>
  </table>
{% endif %}

As you can see, this prevents you from having to hard-code any values into the template.

The syntax of this table is also compatible with datatables, so you if you load the CSS and JS files as per the zero configuration example then your table becomes prettier and can have a builtin search bar and pagination. Let me know if you need further direction on how to do this.

v25
  • 7,096
  • 2
  • 20
  • 36
  • It worked! Exactly what I needed! Thanks man! There won't be any user input here, so I don't have to sanitize the inputs. – Rascal May 06 '20 at 03:06
  • what do you call this part of the code? {% if objects %}, I want to read up more on this. Thanks! – Rascal May 06 '20 at 04:13
  • @Rascal That's an `if` clause in [Jinja2 templating syntax](https://jinja.palletsprojects.com/en/2.11.x/templates/). – v25 May 06 '20 at 07:00
  • @Rascal Side note: avoid building complex logic in templates which doesn't strictly need to be done in a template. When getting started it may be tempting to put things like `{% if somevar %}FOO{% else %}BAR{% endif %}` in a template. This works untill you wish to obtain `FOO` or `BAR` based on `somevar` elsewhere within the Python program. Try to keep the templates to *display* logic as much as possible. – v25 May 06 '20 at 07:15