How to display images using upload and cookies

Question:
Hi everyone :slight_smile: , I’m trying to display a basic soundboard for the homeroom teachers at an elementary school. I want to display 5 images that play a sound when clicked on. Each teacher should to be able to add custom images and sounds that will be kept using cookies saved on the users local machine. I’m having problems with uploading and displaying new images.

(https://replit.com/@DannyD17/Displaying-Images-using-Cookies)

from flask import Flask, render_template, request, make_response, flash
from flask_wtf import FlaskForm
from werkzeug.utils import secure_filename
from wtforms import RadioField, SubmitField, FileField
from wtforms.validators import InputRequired, DataRequired
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'
app.config['ALLOWED_EXTENSIONS'] = {'jpg', 'jpeg', 'png', 'gif', 'wav', 'mp3'}
app.config['UPLOAD_FOLDER'] = 'static/soundboard/'



class FileForm(FlaskForm):
    file = FileField(label="File", validators=[InputRequired()])
    image_submit = SubmitField(label="Upload Images Here")
    sound_submit = SubmitField(label="Upload Sounds Here")
  

def allowed_file(filename):
    return '.' in filename and \
    filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

@app.route("/")
@app.route("/index")
def hello():
    return render_template("index.html")


@app.route('/soundboard', methods=["GET", "POST"])
def upload_file():
    form = FileForm()
    radio_button_value = request.form['band']
    if request.method == 'POST':
        if form.validate_on_submit():
            if form.image_submit.data and 'file' in request.files:
# Save each uploaded image to the specified directory
    
                file = request.files['file']
                file = form.file.data
                if file and allowed_file(file.filename):
                    filename = secure_filename(form.file.data.filename)
                    file.save(os.path.join(app.config["UPLOAD_FOLDER"], 'images', filename))
                    

# Set the cookie by first get the radio button value from the form and assigning it to an image cookie variable (i.e. image1, image2, etc.)
# Set the cookie with the image file location
                    response = make_response(render_template('soundboard.html', form=form, filename=filename, radio_id=radio_button_value))
                    response.set_cookie(f'image_cookie', filename)
                    print('cookie set')
                    return response
        
   
    # If no image cookies are set, show the default images
    print('RIGHT HERE')
    return render_template('soundboard.html', form=form, radio_id=radio_button_value)

if __name__ == '__main__':
    app.run()



And Html: 
<!DOCTYPE html>
<html>

<head>
	<title>Play Custom Sound on Click</title>
	<link rel="stylesheet" type="text/css" href="../static/soundboard/css/style.css">
	<script src="../static/jquery-3.6.4.min.js"></script>
	<script src="../static/soundboard/scripts/script.js"></script>
	<style>
		@import url('https://fonts.googleapis.com/css2?family=Acme&display=swap');
	</style>
</head>

<body>
	<div class="container">
		<div class="title">
			<h1>Grade 4B's Super Soundboard</h1>
		</div>
		<ul>
			<li>
				<form class="settings-menu" method="POST" enctype="multipart/form-data">
					{{form.hidden_tag()}}
					{{form.file()}}
					{{ form.image_submit }}
				</form>
				<div class="title">Please select which picture to update here:
				</div>
				<form id="radio_form" class="settings-menu">
					<label><input type="radio" name="band" value="1" checked><span>Pic 1</span></label>
					<label><input type="radio" name="band" value="2"><span>Pic 2</span></label>
					<label><input type="radio" name="band" value="3"><span>Pic 3</span></label>
					<label><input type="radio" name="band" value="4"><span>Pic 4</span></label>
					<label><input type="radio" name="band" value="5"><span>Pic 5</span></label>
				</form>
			</li>
		</ul>
		<ul>
			<li>
				<div class="circle" id="circle1">
					{% if filename and radio_id == '1' %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/' + filename) }}" alt="image"
						width="100%" height="100%">
					{% else %}
					<img src="{{ url_for('static', filename='soundboard/images/bigbird.png')}}">
					{% endif %}
				</div>
			</li>
			<li>
				<div class="circle" id="circle2">
					{% if filename and radio_id == '2' %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/' + filename) }}" alt="image"
						width="100%" height="100%">
					{% else %}
					<img src="{{ url_for('static', filename='soundboard/images/cookiemonsta.png')}}"
						alt="Cookie Monsta">
					{% endif %}
				</div>
			</li>
			<li>
				<div class="circle" id="circle3">
					{% if filename and radio_id == '3' %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/' + filename) }}" alt="image"
						width="100%" height="100%">
					{% else %}
					<img src="{{ url_for('static', filename='soundboard/images/ernie.png')}}" alt="Ernie">
					{% endif %}
				</div>
			</li>
			<li>
				<div class="circle" id="circle4">
					{% if filename and radio_id == '4' %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/' + filename) }}" alt="image"
						width="100%" height="100%">
					{% else %}
					<img src="{{ url_for('static', filename='soundboard/images/elmo.png')}}" alt="Elmo">
					{% endif %}
				</div>
			</li>
			<li>
				<div class="circle" id="circle5">
					{% if filename and radio_id == '5' %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/' + filename) }}" alt="image"
						width="100%" height="100%">
					{% else %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/oscar.png')}}" alt="Oscar">
					{% endif %}
				</div>
			</li>
		</ul>
	</div>
	<button id="settings-button">Settings</button>
	<audio id="audio1" src="{{ url_for('static', filename='../static/soundboard/sounds/bonus.mp3')}}"></audio>
	<audio id="audio2" src="{{ url_for('static', filename='../static/soundboard/sounds/ding.mp3')}}"></audio>
	<audio id="audio3" src="{{ url_for('static', filename='../static/soundboard/sounds/peacock.mp3')}}"></audio>
	<audio id="audio4" src="{{ url_for('static', filename='../static/soundboard/sounds/punch.mp3')}}"></audio>
	<audio id="audio5" src="{{ url_for('static', filename='../static/soundboard/sounds/store.mp3')}}"></audio>
</body>

</html>

I googled up some stuff and there are several issues with it.
Make sure you have the necessary folders in your project structure. Create the following directories if they don’t exist:
static/soundboard/images: To store the uploaded images.
static/soundboard/sounds: To store the audio files.
Update the form action in your HTML code to point to the correct endpoint (/soundboard ) and set the method to POST : <form class="settings-menu" method="POST" action="/soundboard" enctype="multipart/form-data">

In the upload_file function, you need to change the line radio_button_value = request.form[‘band’] to:
radio_button_value = request.form.get('band')

In the upload_file function, update the line form.image_submit.data to form.image_submit.data : if form.image_submit.data and 'file' in request.files:

Modify the line file = form.file.data to file = request.files['file']

Change the line file.save(os.path.join(app.config["UPLOAD_FOLDER"], 'images', filename)) to:
file.save(os.path.join(app.config["UPLOAD_FOLDER"], 'images', filename))

Update the paths of the images in your HTML code. Replace instances of '../static/soundboard/images/' with '../static/soundboard/images/'

This took like an hour or more to process and look up, so please tell me if this helps make it work.

Hey DefendyPug thanks soo much for your reply! Thanks for taking the time to help out. I made most of the changes you suggested thanks!

But some of your suggestions seemed confusing to me:

Change the line file.save(os.path.join(app.config["UPLOAD_FOLDER"], 'images', filename)) to:
file.save(os.path.join(app.config["UPLOAD_FOLDER"], 'images', filename))

Update the paths of the images in your HTML code. Replace instances of '../static/soundboard/images/' with '../static/soundboard/images/'

These lines in particular seemed confusing because you don’t seem to be suggesting any changes?
Currently I’ve updated my code and actually have everything finally functional. I do now have a new problem (haha - always the way right?):

While my current code works, its so clunky. If you have (or anyone else wants to chip in with) any suggestions, feel free! What’s the better way than having to set 5 hard coded variables to my image cookies I wonder? Thought about using a for loop somehow but having trouble with it.

from flask import Flask, render_template, request, make_response
from flask_wtf import FlaskForm
from werkzeug.utils import secure_filename
from wtforms import SubmitField, FileField
from wtforms.validators import InputRequired
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'
app.config['ALLOWED_EXTENSIONS'] = {'jpg', 'jpeg', 'png', 'gif', 'wav', 'mp3'}
app.config['UPLOAD_FOLDER'] = 'static/soundboard/'



class FileForm(FlaskForm):
    file = FileField(label="File", validators=[InputRequired()])
    image_submit = SubmitField(label="Upload Images Here")
    sound_submit = SubmitField(label="Upload Sounds Here")
  

def allowed_file(filename):
    return '.' in filename and \
    filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

@app.route("/")
@app.route("/index")
def hello():
    return render_template("index.html")


@app.route('/soundboard', methods=["GET", "POST"])
def uploadImage():
    form = FileForm()
    radio_id = request.form.getlist('radio_form')
    image_cookie_1 = request.cookies.get("radio_id['0']")
    image_cookie_2 = request.cookies.get("radio_id['1']")
    image_cookie_3 = request.cookies.get("radio_id['2']")
    image_cookie_4 = request.cookies.get("radio_id['3']")
    image_cookie_5 = request.cookies.get("radio_id['4']")
    
    if request.method == 'POST':
        if form.validate_on_submit():
            if form.image_submit.data and 'file' in request.files:    
                file = request.files['file']
                
                if file and allowed_file(file.filename):
                    filename = secure_filename(form.file.data.filename)
                    file.save(os.path.join(app.config["UPLOAD_FOLDER"], 'images', filename))  
                    response = make_response(render_template('soundboard.html', form=form, radio_id=radio_id, filename=filename, image_cookie_1=image_cookie_1, image_cookie_2=image_cookie_2, image_cookie_3=image_cookie_3, image_cookie_4=image_cookie_4, image_cookie_5=image_cookie_5))
                    response.set_cookie(f'radio_id{radio_id}', filename, max_age=60*60*24*365*2)
                    return response        
        
   
    # If no image cookies are set, show the default images
    print('RIGHT HERE')
    return render_template('soundboard.html', form=form, radio_id=radio_id, image_cookie_1=image_cookie_1, image_cookie_2=image_cookie_2, image_cookie_3=image_cookie_3, image_cookie_4=image_cookie_4, image_cookie_5=image_cookie_5)

if __name__ == '__main__':
    app.run()
<div class="title">
			<h1>Grade 5Furry's Super Soundboard</h1>
		</div>
		<ul>
			<li>
				<div class="title">Please select which picture to update here:
				</div>
				<form id="image_upload_form" class="settings-menu" method="POST" enctype="multipart/form-data">
					{{form.hidden_tag()}}
					{{form.file()}}
					{{ form.image_submit }}

					<label><input type="radio" name="radio_form" value="0" checked><span>Pic 1</span></label>
					<label><input type="radio" name="radio_form" value="1"><span>Pic 2</span></label>
					<label><input type="radio" name="radio_form" value="2"><span>Pic 3</span></label>
					<label><input type="radio" name="radio_form" value="3"><span>Pic 4</span></label>
					<label><input type="radio" name="radio_form" value="4"><span>Pic 5</span></label>

				</form>
			</li>
		</ul>
		<ul>
			<li>
				<div class="circle" id="circle1">

					{% if filename and radio_id == ['0'] %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/'+filename) }}" alt="image"
						width="100%" height="100%">

					{% elif request.cookies.get("radio_id['0']") %}

					<img src="{{ url_for('static', filename='../static/soundboard/images/'+image_cookie_1) }}"
						alt="image" width="100%" height="100%">

					{% else %}
					<img src="{{ url_for('static', filename='soundboard/images/bigbird.png')}}">
					{% endif %}
				</div>
			</li>
			<li>
				<div class="circle" id="circle2">
					{% if filename and radio_id == ['1'] %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/'+filename) }}" alt="image"
						width="100%" height="100%">

					{% elif request.cookies.get("radio_id['1']") %}
					<img src="{{ url_for('static', filename='../static/soundboard/images/'+image_cookie_2) }}"
						alt="image" width="100%" height="100%">
					{% else %}
					<img src="{{ url_for('static', filename='soundboard/images/cookiemonsta.png')}}"
						alt="Cookie Monsta">
					{% endif %}
				</div>
		```

Thanks again for all your help Pug :)

Sorry that some of the suggestions we’re confusing, Lots of it i was just scrounging for information on google and from piers.

Use a loop to dynamically set and retrieve the cookie values

I hope this code works, im bad at python+html

from flask import Flask, render_template, request, make_response
from flask_wtf import FlaskForm
from werkzeug.utils import secure_filename
from wtforms import SubmitField, FileField
from wtforms.validators import InputRequired
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'
app.config['ALLOWED_EXTENSIONS'] = {'jpg', 'jpeg', 'png', 'gif', 'wav', 'mp3'}
app.config['UPLOAD_FOLDER'] = 'static/soundboard/'

class FileForm(FlaskForm):
    file = FileField(label="File", validators=[InputRequired()])
    image_submit = SubmitField(label="Upload Images Here")
    sound_submit = SubmitField(label="Upload Sounds Here")

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

@app.route("/")
@app.route("/index")
def hello():
    return render_template("index.html")

@app.route('/soundboard', methods=["GET", "POST"])
def uploadImage():
    form = FileForm()
    radio_id = request.form.getlist('radio_form')
    image_cookies = []

    for i in range(5):
        cookie_name = f"radio_id['{i}']"
        image_cookie = request.cookies.get(cookie_name)
        image_cookies.append(image_cookie)

    if request.method == 'POST':
        if form.validate_on_submit():
            if form.image_submit.data and 'file' in request.files:
                file = request.files['file']
                if file and allowed_file(file.filename):
                    filename = secure_filename(form.file.data.filename)
                    file.save(os.path.join(app.config["UPLOAD_FOLDER"], 'images', filename))
                    response = make_response(render_template('soundboard.html', form=form, radio_id=radio_id, image_cookies=image_cookies))
                    for i, cookie_name in enumerate(image_cookies):
                        response.set_cookie(f'radio_id[{i}]', filename, max_age=60*60*24*365*2)
                    return response

    # If no image cookies are set, show the default images
    print('RIGHT HERE')
    return render_template('soundboard.html', form=form, radio_id=radio_id, image_cookies=image_cookies)

if __name__ == '__main__':
    app.run()
1 Like

In your HTML you can use loops to handle your image cookies and image display:

{% for i in range(5) %}
    <li>
        <div class="circle" id="circle{{ i+1 }}">
            {% if filename and radio_id == str(i) %}
            <img src="{{ url_for('static', filename='../static/soundboard/images/'+filename) }}" alt="image" width="100%" height="100%">

            {% elif request.cookies.get("radio_id['"+str(i)+"']") %}
            <img src="{{ url_for('static', filename='../static/soundboard/images/'+image_cookies[i]) }}" alt="image" width="100%" height="100%">

            {% else %}
            <img src="{{ url_for('static', filename='soundboard/images/defaultpath.png')}}">

            {% endif %}
        </div>
    </li>
{% endfor %}

Replace defaultpath.png with your actual default image paths.

1 Like

I like this solution more than compared to my for loop, that seems alot more straight forward.