0

Python Flask: Unable to make the python flask variable visible to another if block within the html template file as the "with" statement scope ends with if block. Tried to place the if block above the for loop but it does not take.

The key:value list has something like this: "{subject: Maths, UnitTest1-Score: 90, UnitTest2-Score: 95,UnitTest2-Score: 98 }" Would like to pass the subject_name variable to second if statement "if key == 'UnitTest3'" as interested in referring the respective subject and then update marks in the database. Since the variable is defined (with 'with' statement)in the first if statement " if key == 'Subject' %}. Tried different ways however the context does not move forward after the first if block. Tried to add a "with subject_name='' " after 4th line "if key" so that it can be visible in second if "if key == 'Subject'" however it gives error that the subject_name is undefined if used in second if "if key == 'Subject'" I believe jinja2 supports this. Any help appreciated.

{% block content %}
{% for i in all_subjects %}
<article>
{%for key, value in i.items() %}
    {% if key %}    
        {% if key == 'Subject' %}

            {% with subject_name = value %}

            {% with subject = subject_db.find_one({'subject_name': subject_name}) %}
            {% if subject %}

                <div>
                    <a  href="#" >{{subject['subject_name']}}</a>
                </div>

            {% endif %}
            {% endwith %}
            {% endwith %}

        {% endif %}
        {% if key == 'UnitTest3' %}
            {% with marks = value  %}
            <form  action="" method='POST'>
                <div>
                    <label>  Marks: <input type="number" name="total_marks" min="0" value=0 oninput="this.value = Math.abs(this.value)"> </label>
                    <button type="submit">Update</button>

                </div>
            </form>
            {% endwith %}

        {% endif %}

    {% endif %}
{% endfor %}
</article>
{% endfor %}  
{% endblock content %}
Anand
  • 71
  • 9

1 Answers1

0

You are attempting to do things in Jinja which are much better suited to python. In addition, you seem to be passing in a single dictionary with 2 different kinds of objects in it. This is confusing and unnecessary.

You should process and prepare your data completely in python and then pass the appropriate objects/dictionaries to Jinja for display. A good rule of thumb is that you should avoid database calls from within Jinja. Take care of that in the Flask view method.

I would also point out that key/value pairs will come out of i in an unpredictable order. And that you can't have a dictionary item with None as the key value, so the {% if key %} check can be removed.

Once you have your data structured correctly, you'll be able to do something like this:

render_template('subjects.html', subjects=all_subjects, marks=all_marks)
{% block content %}
{% for s in subjects %}
    <article>
        <div class="subject">
            <a  href="#" >{{ subject.name }}</a>
        </div>
    </article>
{% endfor %}
{% for m in marks %}
    <article>
        <div>
            <form  action="" method='POST'>
                <label for="total_marks">Marks</label>
                <input type="number" id="total_marks" min="0" value="{{ m.value }}" oninput="this.value = Math.abs(this.value)">
                <button type="submit">Update</button>
            </form>
        </div>
    </article>
{% endfor %}
{% endblock content %}

Last thing: "unit test" has a particular meaning in software, and you should avoid using that term to refer to anything else as it will add confusion for the next person who inherits your code.

Nick K9
  • 3,885
  • 1
  • 29
  • 62
  • Thank you https://stackoverflow.com/users/1749551/nick-k9. Appreciate the time taken to respond on this. I understand the points you made. I used a sample code to describe what I was looking for since my other code is too big. – Anand Jun 20 '19 at 18:55
  • May be I used a bad example. All I need is the following: How do I define a variable which is accessible in all if statements from my code updated with the original post where Iam matching the key with key found in the loop. I used {% if key %} to see that whether I can add a variable with "with" statement soon after this if statement so that it can cover the entire block. – Anand Jun 20 '19 at 19:11
  • Think of the document contents like this where all the document contents are like array with simple key : value pairs without any multi levels. I want to pass the document key "_id" value which is a like a unique identifier to the next if statement which matches the next key like username or email in the document. I needed the simple variable which can take this "_d" 's value and pass it for my purpose of matching the "_id" and then update the corresponding next key value to something else since I would be having multiple "_id" s which I need to match the one which Iam looking for. – Anand Jun 20 '19 at 19:20
  • Only ask is how to define such a variable like "_id" which can span through the template without giving undefined error when accessed inside any if block. Thanks in advance. Not sure why jinja2 is putting restriction here where as we can define any of these variables within the python code however when used in template there is a restriction. – Anand Jun 20 '19 at 19:23
  • OK, thanks for clarifying. In that case, I think your question is a duplicate of this one: https://stackoverflow.com/questions/4870346/can-a-jinja-variables-scope-extend-beyond-in-an-inner-block – Nick K9 Jun 21 '19 at 14:02