I have been struggling with this for nearly a week. I am learning Flask, building an application for collectors. Collectors can view the database, but can add/edit only after login. The app requires for an item to be added first, before a photo can be added under the same page. After a photo is added, the app returns back to the viewing page. That requires an id to be passed between the app routes. At this stage I am either doing something absolutely stupid while passing values, or I have issues with my sessions. Simplified version of app.py can be seen below (certain routes are omitted, I can provide them if necessary): import os import sqlite3 from flask import Flask, flash, jsonify, redirect, render_template, request, session, url_for from flask_session import Session from functools import wraps from werkzeug.security import check_password_hash, generate_password_hash from werkzeug.utils import secure_filename # Configure application UPLOAD_FOLDER = 'static\\uploads' ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'} app = Flask(__name__) app.config\['UPLOAD_FOLDER'\] = UPLOAD_FOLDER app.config\['SECRET_KEY'\] = '123123cdsfqernwkfnvgfelnrvgn3v5gq35kj' # Configure session to use filesystem (instead of signed cookies) app.config\["SESSION_PERMANENT"\] = False app.config\["SESSION_TYPE"\] = "filesystem" Session(app) # Database db = sqlite3.connect('database.db', check_same_thread=False) cursor = db.cursor() def login_required(f): """ Decorate routes to require login. https://flask.palletsprojects.com/en/latest/patterns/viewdecorators/ """ @wraps(f) def decorated_function(*args, **kwargs): if session.get("user_id") is None: return redirect("/login") return f(*args, **kwargs) return decorated_function @app.route("/view/\<p_id\>", methods=\["GET", "POST"\]) def view(p_id): """View an individual P""" rows = cursor.execute("SELECT * FROM pez WHERE p_id = ?", (p_id, )).fetchall()[0] series = rows[1] subseries = rows[2] name = rows[3] issue = rows[4] if request.method == "GET": return render_template("view.html", series = series, subseries = subseries, name = name, issue = issue, p_id = p_id) @app.route("/add_main_img", methods=\["GET", "POST"\]) @login_required def add_main_img(): """Add new item to database""" p_id = request.args.get("p_id") if request.method == "GET": return render_template("add_main_img.html") else: # check if there is a file part if 'file' not in request.files: flash('No file part') return render_template("add_main_img.html") file = request.files['file'] # check filename is not empty (i.e. user didn't select a file) and allowed and upload it if file.filename == '': flash("No image selected for upload") return redirect(request.url) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) flash("Image succesfully uploaded") return redirect(url_for('view', p_id=p_id)) else: flash("Allowed image types are .png, .jpg, .jpeg") return redirect(request.url) view.html: {% extends "layout.html" %} {% block title %} View {% endblock %} {% block main %} <table> <tr> <th>Series</th> <td>{{ series }}</td> </tr> <tr> <th>Subseries</th> <td>{{ subseries }}</td> </tr> <tr> <th>Dispenser/Character</th> <td>{{ name }}</td> </tr> <tr> <th>Issue</th> <td>{{ issue }}</td> </tr> </table> <button type="submit" id="main_img" name="main_img"><a href="{{ url_for('add_main_img', p_id=p_id) }}">Add main/profile img</a></button> {% endblock %} add_image: {% extends "layout.html" %} {% block title %} Add main image {% endblock %} {% block main %} <h2>Upload new</h2> <form action="/add_main_img" method="post" enctype = "multipart/form-data"> <div> <input class="form-control mx-auto w-auto" type="file" name="file" placeholder="Add Profile Image"> </div> <input type="submit" > </form> {% endblock %} The route view -> add_image -> upload seems to work, but it's failing to pass the id afterwards. I then get the following traceback (not the complete one, let me know if more details are needed): werkzeug.routing.exceptions.BuildError werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'view'. Did you forget to specify values ['p_id']? File "C:\Users\denchevd\Desktop\personal\Code\FinalProject\app.py", line 37, in decorated_function return f(*args, **kwargs) ^^^^^^^^^^^^^^^^^^ File "C:\Users\denchevd\Desktop\personal\Code\FinalProject\app.py", line 415, in add_main_img return redirect(url_for('view', p_id=p_id)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ And this is where things get funky. I managed to partially redeem the situation by converting the def variable to a string. However, I can't find any reason why that worked: @app.route("/add_main_img", methods=["GET", "POST"]) @login_required def add_main_img(): """Add new item to database""" p_id = str(request.args.get("p_id")) This made the app to get stuck at a different place at @view: IndexError IndexError: list index out of range File "C:\Users\denchevd\Desktop\personal\Code\FinalProject\app.py", line 235, in view rows = cursor.execute("SELECT * FROM pez WHERE p_id = ?", (p_id, )).fetchall()[0] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ It seems that p_id is being passed as 'None' and is not convertible to int. am I doing something stupid while passing the values or am I having a problem with the session? If the latter, please suggest a fix to it, as I am unable to work it out on my own. Continue reading...