[Python] Flask - Problem with passing variables between routes OR with sessions

Discussão em 'Python' iniciado por Stack, Março 26, 2025.

  1. Stack

    Stack Membro Participativo

    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...

Compartilhe esta Página