Flask 烧瓶-request.args.getlist-只能读取一次?

Flask 烧瓶-request.args.getlist-只能读取一次?,flask,python-3.8,werkzeug,url-for,Flask,Python 3.8,Werkzeug,Url For,在我的Flask应用程序中,我正在重定向到另一个页面,其中包含一个参数,如下所示: return redirect(url_for("edit.editFunction", plants=thisPlant)) 然后,在另一个文件中,我用以下行读取该参数: # Get arguments from url_for in administration thisPlant = request.args.getlist("plants")

在我的Flask应用程序中,我正在重定向到另一个页面,其中包含一个参数,如下所示:

return redirect(url_for("edit.editFunction", plants=thisPlant))
然后,在另一个文件中,我用以下行读取该参数:

    # Get arguments from url_for in administration
    thisPlant = request.args.getlist("plants")
    print(thisPlant)

    # Get ID on edit plant
    plant_id = thisPlant[0]
    print(plant_id)
到目前为止,这是我的控制台返回的好消息:

['1', 'aa', '11', '11', 'https://i.ibb.co/QNJnLR8/empty.png', 'aa', '1']
1
但当我想在同一个文件上使用post方法时,我得到以下结果:

    plant_id = thisPlant[0]
IndexError: list index out of range
这怎么可能?我应该读
1
有人能发现我的错误吗

以下是我使用此变量的完整文件:

import sqlite3
import traceback
import sys
import re
import os

from flask import Blueprint, render_template, redirect, session, request, flash, get_flashed_messages
from application import getUserName, getUserPicture, login_required, confirmed_required, getUserRole, role_required, uploadPicture
from werkzeug.utils import secure_filename

# Set Blueprints
edit = Blueprint('edit', __name__,)

@edit.route("/edit", methods=["GET", "POST"])
@login_required
@confirmed_required
@role_required
def editFunction():    

    # Force flash() to get the messages on the same page as the redirect.
    get_flashed_messages()

    if request.method == "POST":

        # Get variables
        plant_id = request.form.get("plant_id")
        name = request.form.get("name")
        stock = request.form.get("stock")
        price = request.form.get("price")
        description = request.form.get("description")

        # Ensure the plant name was submitted
        if not name:
            flash("must provide plant name")
            return redirect("/edit")

        # Ensure the plant name fits server-side
        if not re.search("^[a-zA-Z0-9]{1,50}$", name):
            flash("Invalid plant name")
            return redirect("/edit")

        # Ensure the plant stock was submitted
        if not stock:
            flash("must provide plant stock")
            return redirect("/edit")

        # Ensure the plant stock fits server-side
        if not re.search("^[0-9]+$", stock):
            flash("Invalid plant stock")
            return redirect("/edit")

        # Ensure the plant price was submitted
        if not stock:
            flash("must provide plant price")
            return redirect("/edit")

        # Ensure the plant price fits server-side
        if not re.search("^[0-9]+$", stock):
            flash("Invalid plant price")
            return redirect("/edit")

        # Ensure the plant description was submitted
        if not description:
            flash("must provide plant description")
            return redirect("/edit")

        # Ensure the plant description fits server-side
        if not re.search("^(?!;).+", description):
            flash("Invalid plant description")
            return redirect("/edit")

        # Check show bool status
        show = "show" in request.form


        # Update plant name, stock, price, description and show status into the table
        try:

            sqliteConnection = sqlite3.connect("database.db")
            cursor = sqliteConnection.cursor()

            cursor.execute("UPDATE plants SET name=:name, stock=:stock, price=:price, description=:description, show=:show WHERE id=:plant_id;", {"name": name, "stock": stock, "price": price, "description": description, "show": show, "plant_id": plant_id})
            sqliteConnection.commit()

            cursor.close()

        except sqlite3.Error as error:
        
            print("Failed to read data from sqlite table", error)
            print("Exception class is: ", error.__class__)
            print("Exception is", error.args)

            print('Printing detailed SQLite exception traceback: ')
            exc_type, exc_value, exc_tb = sys.exc_info()
            print(traceback.format_exception(exc_type, exc_value, exc_tb))

        finally:

            if (sqliteConnection):
                sqliteConnection.close()

        # Save, upload and delete picture file
        file = request.files["picture"]

        if file and file.filename:

            filename = secure_filename(file.filename)
            file.save(os.path.join("./static", filename))
            upload = uploadPicture("./static/" + filename)
            os.remove("./static/" + filename)

            # Update database with new image url 
            try:

                sqliteConnection = sqlite3.connect("database.db")
                cursor = sqliteConnection.cursor()
                
                cursor.execute("UPDATE plants SET picture=:picture WHERE name=:name;", {"picture": upload, "name": name})
                sqliteConnection.commit()

                cursor.close()

            except sqlite3.Error as error:
            
                print("Failed to read data from sqlite table", error)
                print("Exception class is: ", error.__class__)
                print("Exception is", error.args)

                print('Printing detailed SQLite exception traceback: ')
                exc_type, exc_value, exc_tb = sys.exc_info()
                print(traceback.format_exception(exc_type, exc_value, exc_tb))

            finally:

                if (sqliteConnection):
                    sqliteConnection.close()

        flash("Plant edited")
        return redirect("/administration")


    else:
        # Get arguments from url_for in administration
        thisPlant = request.args.getlist("plants")
    
        return render_template("edit.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), plants=thisPlant)
这是完整的控制台输出:

127.0.0.1 - - [05/Jan/2021 22:20:44] "GET /administration HTTP/1.1" 200 -
127.0.0.1 - - [05/Jan/2021 22:20:44] "GET /static/styles.css HTTP/1.1" 200 -
127.0.0.1 - - [05/Jan/2021 22:20:45] "POST /administration HTTP/1.1" 302 -
['1', 'aa', '11', '11', 'https://i.ibb.co/QNJnLR8/empty.png', 'aa', '1']
1
127.0.0.1 - - [05/Jan/2021 22:20:45] "GET /edit?plants=1&plants=aa&plants=11&plants=11&plants=https%3A%2F%2Fi.ibb.co%2FQNJnLR8%2Fempty.png&plants=aa&plants=1 HTTP/1.1" 200 -
127.0.0.1 - - [05/Jan/2021 22:20:45] "GET /static/styles.css HTTP/1.1" 200 -
[]
[2021-01-05 22:20:53,655] ERROR in app: Exception on /edit [POST]
Traceback (most recent call last):
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/benoit/Documents/CrazyPlantCrew/application.py", line 94, in decorated_function
    return f(*args, **kwargs)
  File "/home/benoit/Documents/CrazyPlantCrew/application.py", line 109, in decorated_function
    return f(*args, **kwargs)
  File "/home/benoit/Documents/CrazyPlantCrew/application.py", line 124, in decorated_function
    return f(*args, **kwargs)
  File "/home/benoit/Documents/CrazyPlantCrew/routes/edit.py", line 28, in editFunction
    plant_id = thisPlant[0]
IndexError: list index out of range
127.0.0.1 - - [05/Jan/2021 22:20:53] "POST /edit HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
    raise value
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/benoit/Documents/CrazyPlantCrew/application.py", line 94, in decorated_function
    return f(*args, **kwargs)
  File "/home/benoit/Documents/CrazyPlantCrew/application.py", line 109, in decorated_function
    return f(*args, **kwargs)
  File "/home/benoit/Documents/CrazyPlantCrew/application.py", line 124, in decorated_function
    return f(*args, **kwargs)
  File "/home/benoit/Documents/CrazyPlantCrew/routes/edit.py", line 28, in editFunction
    plant_id = thisPlant[0]
IndexError: list index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/werkzeug/serving.py", line 304, in run_wsgi
    execute(self.server.app)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/werkzeug/serving.py", line 292, in execute
    application_iter = app(environ, start_response)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 2464, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 2450, in wsgi_app
    response = self.handle_exception(e)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1881, in handle_exception
    return self.finalize_request(server_error, from_error_handler=True)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 1968, in finalize_request
    response = self.make_response(rv)
  File "/home/benoit/Documents/CrazyPlantCrew/venv/lib/python3.8/site-packages/flask/app.py", line 2097, in make_response
    raise TypeError(
TypeError: The view function did not return a valid response. The function either returned None or ended without a return statement.

编辑:添加表单

{% extends "layout.html" %}

{% block title %}
    Edit
{% endblock %}

{% block navigation %}
    {% if role == "admin" %}
        <li><a href="/administration">Administration</a></li>
        <li><a href="/communication">Update blog</a></li>
        <li><a href="/newsletter">Send newsletter</a></li>
    {% endif %}
{% endblock %}

{% block main %}
        <form action="/edit" method="post" enctype="multipart/form-data">
            <div>
                <input type='hidden' name='plant_id' value='{{ plants[0]}}'>
            </div>
            <div>
                <input id="name" autocomplete="off" autofocus class="form-control" name="name" placeholder="Name" type="text" value="{{ plants[1] }}">
            </div>
            <br>
            <div>
                <input id="stock" autocomplete="off" autofocus class="form-control" name="stock" placeholder="Stock" type="number" min="0" value="{{ plants[2] }}">
            </div>
            <br>
            <div>
                <input id="price" autocomplete="off" autofocus class="form-control" name="price" placeholder="Price" type="number" min="0" value="{{ plants[3] }}">
            </div>
            <br>
            <div>
                <textarea id="description" autocomplete="off" autofocus class="form-control" name="description" placeholder=" Description" type="text" cols="100" rows="10">{{ plants[5] }}</textarea>
            </div>
            <br>
            <div>
                <input type="file" id="picture" name="picture">
            </div>
            <br>
            <div>
                <input type="checkbox" id="show" name="show" value="show" checked="{{ plants[6] }}">
                <label for="show"> Show?</label><br>
            </div>
            <br>
            <div>
                <button id="submit" type="submit" name="submit" value="submit">Save.</button>
            </div>
            <br>
            <div>
                <a href="/administration">Back</a>
            </div>
        </form>
{% endblock %}
{%extends“layout.html”%}
{%block title%}
编辑
{%endblock%}
{%block-navigation%}
{%if role==“admin”%}
  • {%endif%} {%endblock%} {%block main%}


    {{植物[5]}

    显示?

    拯救
    {%endblock%}

    EDIT2:为我的代码添加解决方案-非常感谢v25

    如果我没看错的话

    request.args.getlist
    仅获取作为URL参数发布的数据,因此在POST请求期间尝试访问
    plants[0]
    时出现
    keyror
    。请注意,在服务器日志中,
    print(thisPlant)
    在POST请求期间提供了一个空列表:
    []

    看起来您只需要重新构造该路由,因此问题行只在GET请求中执行

    比如:

    
    def editFunction():    
    
        # Force flash() to get the messages on the same page as the redirect.
        get_flashed_messages()
    
        if request.method = 'GET':
            # Get arguments from url_for in administration
            thisPlant = request.args.getlist("plants")
            print(thisPlant)
    
            # Get ID on edit plant
            plant_id = thisPlant[0]
            print(plant_id)
    
            # Do return here, rather than in 'else' statement at bottom of file
            return render_template("edit.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), plants=thisPlant)
    
        elif request.method == "POST":
    
            # code to handle POST Request
    
            # ...
    
            flash("Plant edited")
            return redirect("/administration")
    

    问题是我需要
    plant\u id=thisPlant[0]
    的值,因为这是我需要更新的数据库中的
    id
    ,所以它必须在POST请求中<代码>游标。执行(“更新植物集名称=:名称,股票=:股票,价格=:价格,描述=:描述,显示=:显示其中id=:植物id;”,{“名称”:名称,“股票”:股票,“价格”:价格,“描述”:描述,“显示”:显示,“植物id”:植物id})我为什么不能访问此变量?它在同一个文件中。或者是否有其他方法可以从另一个文件中的
    返回重定向(url_for(“edit.editFunction”,plants=thisPlant))
    访问数据,而不是使用
    request.args.getlist(“plants”)
    ?@Benoî您的表单中没有包含模板代码,但是解决这个问题的最快方法可能是在表单
    中插入一个隐藏字段,然后使用
    request.form.get(“plant_id”)
    在post路径中获取它。哦,我刚刚添加了它。这个快速修复正是我所需要的。谢谢你的教导。非常感谢您抽出时间。