Python Flask Basics Character Builder Starting the Builder

Hasan Ahmad
Hasan Ahmad
6,726 Points

Jinja 2 error, options is undefined

I was following along with the video and i got a jinja 2 error. It told me that options is undefined. Here is all the code:

app.py

from flask import (Flask, render_template, redirect, url_for, request, make_response)
import json
from options import DEFAULTS


app = Flask(__name__)


def get_saved_data():
    try:
        data = json.loads(request.cookies.get('character'))
    except TypeError:
        data = {}
    return data

@app.route('/')
def index():
    return render_template('builder.html', saves=get_saved_data())

@app.route('/builder')
def builder():
    return render_template('builder.html', 
                           saves=get_saved_data(),
                          options=DEFAULTS)

@app.route('/save', methods=['POST'])
def save():
    response = make_response(redirect(url_for('index')))
    data = get_saved_data()
    data.update(dict(request.form.items()))
    response.set_cookie('character', json.dumps(data))
    return response

app.run(debug=True, host='0.0.0.0', port=8000)

index.html

{% extends "layout.html" %}
{% block content %}
<!--Enter Name -->
<div class="enter-name">
    <div class="grid-100">
        <img src="/static/img/bear_avatar.svg" class="bear-avatar" />
    </div>
    <div class="grid-100">
        <form action="{{ url_for('save') }}" method="POST">
            <label>Name your bear</label>
            <input type="text" name="name" value="{{ saves.get('name', '') }}" autofocus>
            <input type="submit" value="Let's build it!">
        </form>
    </div>
</div>
{% endblock %}

builder.html

{% extends "layout.html" %}

{% block content %}
<!--Build Area -->
<form action="" method="POST" class="wrap no-top">
    <div class="grid-100 row">
        <div class="grid-30">
            <div class="title">
                <input type="text" name="name" value="{{ saves.get('name', '') }}">
            </div>
        </div>
        <div class="grid-70">
            <div class="colors">
                 {% for color in options['colors'] %}
                    <input type="radio" id="{{ color }}" name="colors" value="{{ color }}"
                        {% if saves.get('color') == color %}checked{% endif %}>
                    <label for="{{ color }}"></label>
                {% endfor %}
                <button class="btn">Update</button>
            </div>
        </div>
        <div id="bear" class="grid-100">
            <div class="bear-body"><img src="/static/img/bear_body.svg" /></div>
            <div class="head"><img src="/static/img/bear_face.svg" /></div>
            <div class="nose"><img src="/static/img/bear_nose.svg" /></div>
        </div>
        <div class="items">
        </div>
    </div>
</form>

{% endblock %}

options.py

DEFAULTS = {
    "shirts": [
        "black",
        "green",
        "orange",
        "pink",
        "red",
        "teal",
        "purple"
    ],
    "pants": [
        "black",
        "blue",
        "green",
        "grey",
        "stars",
        "stripes",
        "tiger"
    ],
    "hat": [
        "black-baseball",
        "black-beanie",
        "bowler",
        "headband",
        "party",
        "pink-baseball",
        "pink-beanie"
    ],
    "glasses": [
        "optical-black",
        "optical-blue",
        "optical-purple",
        "optical-red",
        "optical-yellow",
        "sun-black",
        "sun-red"
    ],
    "footwear": [
        "sandal-pink",
        "sandal-purple",
        "shoes-black",
        "shoes-blue",
        "shoes-grey",
        "shoes-purple",
        "shoes-tiger"
    ],
    "colors": [
        "black",
        "purple",
        "blue",
        "green",
        "yellow",
        "orange",
        "red"
    ]
}

2 Answers

Rich Zimmerman
Rich Zimmerman
24,062 Points

Does it give you a file and line in the error message? To help trace where the error is happening, if it's on the

from options import DEFAULTS

# or

{% for color in options['colors'] %}

Sometimes directories can mess up your imports, so could be an issue there.

Or, i could be wrong here. Try removing the parenthesis from

from flask import (Flask, render_template, redirect, url_for, request, make_response)

They shouldn't be needed and could potentially be the issue.

I am having the same issue and It is saying the error is for the this line.

 {% for color in options['colors'] %}

UPDATE Figured out the issue.

Instead of doing this...

@app.route('/')
 def index():
         return render_template('builder.html', saves=get_saved_data())

@app.route('/builder')
def builder():
    return render_template('
                      builder.html', 
                      saves=get_saved_data(),
                      options=DEFAULTS)

I did this...

@app.route('/')
def index():
    return render_template('
                       builder.html', 
                       saves=get_saved_data(),
                       options=DEFAULTS)

@app.route('/builder')
def builder():
    return render_template('builder.html', saves=get_saved_data())

For those that can't see the difference. I declared options=DEFAULTS in the /index route instead of in the /builder route.

Natalia Parzyk
Natalia Parzyk
2,144 Points

I had the same problem and after checking the ideas given in this tread, inspired by what Eli Cobler have posted, I came up with solution as described below. I have left the definition of options under builder route, so like in the video but I have used lower case characters options = DEFAULTS, rather than OPTIONS=DEFAULTS used by Kenneth in the video, so this part of my working code looks like:

@app.route('/builder')
def builder():
    return render_template(
            'builder.html',
            saves=get_saved_data(),
            options = DEFAULTS )
Marta P.
Marta P.
2,849 Points

I also have the same problem but trying the solution Rich Zimmerman suggested did not work! No file and line in the error message:(

Hasan Ahmad
Hasan Ahmad
6,726 Points

Yup it didnt work, but i somehow solved the problem, dont know how lol