Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Flask Basics Character Builder Starting the Builder

Hasan Ahmad
Hasan Ahmad
6,727 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,063 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,210 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,727 Points

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