Python Flask Basics Character Builder Drawing the Bear

K.D. Harris
K.D. Harris
10,828 Points

Drawing the Bear - Clothing Images

My entire app works without a problem except for the clothing - it just displays a broken image icon near the bear's feet.

My first thought was that I had made a typo in the filepath; but having viewed the video several times quite carefully, I don't think that is the case. It could be there is a typo/mistake I'm not seeing, though.

Here is the code I placed in the builder.html page to render the footwear, for example:

         {% if saves.get('footwear') %}
           <div class="footwear">
             <img src="/static/img/bear_items_footwear-{{ saves['footwear'] }}.svg">
           </div>
         {% endif %}

I placed that^ code underneath the div that contains the bear_body.svg image. Has anyone else experienced this issue?

Here is my code from builder.html:

{% extends "layout.html" %}

{% block content %}
<!--Build Area -->
<form action="{{ url_for('save') }}" 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('colors') == color %}checked{% endif %}>
                <label for="{{ color }}"></label>
              {% endfor %}
                <button class="btn">Update</button>
            </div>
        </div>

        <div id="bear" class="grid-100 bg-{{ saves.get('colors') }}">
            <div class="bear-body"><img src="/static/img/bear_body.svg"></div>
          {% if saves.get('footwear') %}
            <div class="footwear"><img src="/static/img/bear_items_footwear-{{ saves['footwear'] }}.svg"></div>
          {% endif %}

          {% if saves.get('pants') %}
            <div class="pants"><img src="/static/img/bear_items_pants-{{ saves['pants'] }}.svg"></div>
          {% endif %}




          {% if saves.get('shirts') %}
            <div class="shirts"><img src="/static/img/bear_items_shirts-{{ saves['shirts'] }}.svg"></div>
          {% endif %}

            <div class="head"><img src="/static/img/bear_face.svg" /></div>
             {% if saves.get('glasses') %}
            <div class="glasses"><img src="/static/img/bear_items_glasses-{{ saves['glasses'] }}.svg"></div>
          {% endif %}

            <div class="nose"><img src="/static/img/bear_nose.svg" /></div>

          {% if saves.get('hat') %}
            <div class="hat"><img src="/static/img/bear_items_hat-{{ saves['hat'] }}.svg"></div>
          {% endif %}
        </div>

        <div class="items">
          {% for category, choices in options.items() %}
          {% if category != 'colors' %}
          <div class="grid-100 row">
            <div class="grid-20">
              <p class="category-title">{{ category.title() }}</p>
        </div>
            <div class="grid-80">
              <input type="radio" id="no_{{ category }}" name="{{ category }}" value= '' {% if not saves.get(category) %}checked{% endif %}>
              <label for="no_{{ category }}_icon"><img src="/static/img/no-selection.svg"></label>
              {% for choice in choices %}
              <input type="radio" id="{{ category }}-{{ choice }}_icon" name="{{ category }}" "{{ choice }}" {% if saves.get(category) == choice %}checked{% endif %}>
              <label for="{{ category }}-{{ choice }}_icon"><img src="/static/img/{{ category }}-{{ choice }}.svg"></label>
              {% endfor %}
            </div>
          </div>
          {% endif %}
          {% endfor %}
</form>

{% endblock %}

And here is my code from app.py:

import json

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

from options import DEFAULTS

app = Flask(__name__)
app.secret_key = 'fwg4589jbdfjg957e6yh4hg!dff}]\34'

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


@app.route('/')
def index():
  return render_template('index.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():
  flash("Content saved!")
  response = make_response(redirect(url_for('builder'))) 
  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)

3 Answers

Can you check your browser's JavaScript console to see if there are any error messages?

Also, you might need to include the code for the entire builder.html file, and possibly the app.py too. That will help us to determine what might be happening.

K.D. Harris
K.D. Harris
10,828 Points

The console displays the same error message for each of the five clothing items:

Failed to load resource: the server responded with a status of 404 (Not Found)

I don't know what problem that indicates, though, as the clothing images are definitely in the /static/img directory. I will add the code for builder.html and app.py to my original post in a moment, as well.

Does it display the path that it is looking for the images in? Sometimes you'll find with relative file paths that it's not starting from where you expect. i.e. it might be looking from the templates directory, or up a level from where it should be, etc.

And I assume you haven't changed the options.py file.

Josip Dorvak
Josip Dorvak
18,126 Points

My only thought would be that you may have moved the images from that directory by accident? Try checking if the images are there.

I doubt it's related, but you missed a bit of code down towards the bottom of your builder.html:

<input type="radio" id="no_{{ category }}" name="{{ category }}" value= '' {% if not saves.get(category) %}checked{% endif %}>

should be:

<input type="radio" id="no_{{ category }}_icon" name="{{ category }}" value= '' {% if not saves.get(category) %}checked{% endif %}>

Also, my builder.html has most of that code wrapped in form tags, but I'm not sure if that's because I finished the course...:

{% extends "layout.html" %}

{% block content %}
<form action="{{ url_for('save') }}" method="POST" class="wrap no-top">
    <div class="grid-100 row">
    ...
    </div>
</form>

{% endblock %}
K.D. Harris
K.D. Harris
10,828 Points

Ah! :) In the console, it shows the filepath it's using to try to get each image:

/static/img/bear_items_footwear-on.svg

I am still not sure, but it looks like that means there is something wrong with the portions of code used to display the selected clothing item, like this one:

{% if saves.get('pants') %}
            <div class="pants"><img src="/static/img/bear_items_pants-{{ saves['pants'] }}.svg"></div>
          {% endif %}

Maybe I did a typo in one of app.py's views and it's impacting the process by which the selected clothing item is saved. I haven't altered options.py, though. I've most likely typed something incorrectly here, but I'm not sure what.

I'm all out of ideas! You tried adding the form tags?

Any ideas Kenneth Love?