3

I am learning flask and tried to create a web app that accepts a student's name and marks, finds the total of all the marks and display things in a table. But the total always gets displayed as 0.

The code is given below

mark_total.py:

from flask import Flask, render_template, request

app = Flask (__name__)

@app.route('/')
def student():
        return render_template('student.html')

@app.route('/result', methods = ['POST', 'GET'])
def result():
        if request.method == 'POST':
                result = request.form
                return render_template('result.html', result = result)

if __name__ == '__main__':
        app.run(host = '0.0.0.0', debug = True)

student.html:

        <form action = "/result" method = "POST">
                <p>Name <input type = "text" name = "Name" /></p>
                <p>Physics <input type = "text" name = "Physics" /></p>
                <p>Chemistry <input type = "text" name = "chemistry" /></p>
                <p>Maths <input type ="text" name = "Mathematics" /></p>
                <p><input type = "submit" value = "submit" /></p>
        </form>

</body>
</html>

result.html:

<html>
        <head>
                <title>Results</title>
        </head>

        <body>
                <h1>{{result["Name"]}}'s results</h1>
                {% set total = 0 %}
                <table border = 1>
                {% for key, val in result.iteritems() %}
                        {% if key != 'Name' %}
                                {% set total = total|int + val|int %}
                                <tr>
                                        <td>{{ key }}</td>
                                        <td>{{ val }}</td>
                                        <td>{{ total }}</td>
                                </tr>
                        {% endif %}
                {% endfor %}
                <tr>
                        <td>Total</td>
                        <td>{{total}}</td>
                </tr>
                </table>
        </body>
</html>

The html source of the output is as follows:

<html>
 <head>
  <title>Results</title>
 </head>
 <body>
  <h1>ABC's results</h1>
  <table border = 1>
   <tr>
    <td>Mathematics</td>
    <td>100</td>
    <td>100</td>
   </tr>
   <tr>
    <td>chemistry</td>
    <td>100</td>
    <td>100</td>
   </tr>
   <tr>
    <td>Physics</td>
    <td>100</td>
    <td>100</td>
   </tr>
   <tr>
    <td>Total</td>
    <td>0</td>
   </tr>
  </table>
 </body>
</html>

Can someone please help me understand how to solve this?

Karthick S
  • 3,204
  • 6
  • 36
  • 52

2 Answers2

4

The problem is that your total defined inside the loop is not the same total defined (and accessed) outside of loop. This is what local scopes do.

You can overcome this by using a hack like this (adapted from this answer).

<html>
        <head>
                <title>Results</title>
        </head>

        <body>
                <h1>{{result["Name"]}}'s results</h1>
                {% set total = [0] %}
                <table border = 1>
                {% for key, val in result.iteritems() %}
                        {% if key != 'Name' %}
                                {% set _ = total.append(total.pop() + val|int) %}
                                <tr>
                                        <td>{{ key }}</td>
                                        <td>{{ val }}</td>
                                        <td>{{ total[0] }}</td>
                                </tr>
                        {% endif %}
                {% endfor %}
                <tr>
                        <td>Total</td>
                        <td>{{ total[0] }}</td>
                </tr>
                </table>
        </body>
</html>

But I'm really not sure that it is a good idea to do such things in a template. The main idea of templates is to separate the logic (like counting the totals) and the representation, and this is a violation of this principle.

Community
  • 1
  • 1
Ilya V. Schurov
  • 7,687
  • 2
  • 40
  • 78
3

When you change variable value inside a loop does not effect outside of the loop except a dict:

{% set total = {'value': 0} %}
...
    {% if total.update({"value": c|int + total.value|int }) %} {% endif %}
...
    {{total.value}}
metmirr
  • 4,234
  • 2
  • 21
  • 34