首页 > 解决方案 > 如何从 python 和 HTML 的外部文件中请求由列表创建的表单?提出 werkzeug.exceptions.BadRequestKeyError

问题描述

我正在尝试制作一个以单选按钮形式接收用户答案的​​网站。我用for循环制作了单选按钮,并认为我的python代码也可以用for循环接收用户的答案!我对此很陌生,所以很可能是我做错了一些小事。

我认为这可能是因为在 for 循环中,我放了一个request.form[word],也许 request.form 没有得到我在计算函数中放的参数?除此之外,我已经尝试过这个,它似乎没有任何区别。

我已经包含了我的 python 代码的相关部分、txt 文件、测试页的 html 文件以及显示在我的屏幕上的错误。

蟒蛇片段

# imports flask, a function which can redirect the current url
# to a different one, and url_for
from flask import Flask, redirect, url_for, render_template, request, session, flash
import copy

# creating the app
app = Flask(__name__)
app.secret_key = "aC@nth8scdjkfdhfjdsfkdksm12345678910helloworlddlrowolleh"


# when you click on the link, it directs to this page
@app.route("/")
def home():
    return render_template("index.html")


@app.route("/home")
def tohome():
    return redirect(url_for("home"))


# makes a list of the questions
firstpage_questions = list()
with open("firstquestions.txt", "r") as file:
    for i in file:
        firstpage_questions.append(i.rstrip("\n"))

# this deep copy is so if I make any changes to the duplicated list it won't affect the original list.
firstquestions = copy.deepcopy(firstpage_questions)

questlist = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)


# the request method means that if the sight reloads, the user still has their results saved
@app.route("/takethetest", methods=["POST", "GET"])
def takethetest():
    return render_template("takethetest.html", q=firstquestions, answers=questlist)


def calculate(firstq, lastq):
    for word in firstquestions:
        for num in questlist:
          answered = request.form['question ' + str(questlist[num-1])]
          mental_issue = 0
          if firstquestions.index(word) >= firstq and firstquestions.index(word) <= lastq:
            if firstquestions.index(word) % 2 != 0:
              mental_issue += int(answered) * 10
            elif firstquestions.index(word) % 2 == 0:
              mental_issue += (10 - int(answered)) * 10
            else:
              continue
          else:
            break
        #     make this an error handling thingy which posts it onto the website.
        return mental_issue


@app.route("/results", methods=["POST"])
def results():
    if request.method == "POST":
        burn_out = calculate(1, 5)
        stress = calculate(6, 10)
        anxiety = calculate(11, 15)
        return render_template("results.html", b=burn_out, s=stress, a=anxiety)
    else:
        return render_template("results.html")
        

# runs the app, and debug=true means that it reloads the page without
# having to load it on this virtual environment


if __name__ == "__main__":
    app.run(debug=True)

Txt 文件片段

Over the past month, have you been procrastinating more than ever? 1 for nope, 10 for yes too much!
In the last month, how often have you sat down and properly relaxed? Choose 1 for once, and 10 for I relax all the time.
Have you eaten more/less in the past month? From one to ten how much have your eating habits changed?
Do you have perfectionistic tendencies? If yes, pick 1. If you don't care at all that something is screwed up, pick 10.
In the past ten days, how many days have you been completely exhausted and lost all motivation?
How many days in the past ten days have you been having no problem falling asleep, or waking up completely refreshed?
On a scale of one to ten how much do you worry or are nervous about an upcoming social situation?
How many days in the past two weeks have you NOT noticed your heart racing randomly? 1 for heart racing all the time, 10 for not noticing.
How many times a day do you get easily irritated by other people/things? From 1 to 10.
Do you ever feel ‘on edge’ or unsettled? 1 for all the time, 10 for no.
How many times have you felt like you’ve been on ‘low power mode’ in the last two weeks? 1 for 1 day or less, 10 for 10 days or more.
How many days in the past two weeks has your skin been normal (no extra pimples, sores etc.)? 1 for my skin has been so bad, to 10 for perfect skin.
Have you ever caught yourself clenching your jaw or grinding your teeth in the past month? 1 for never, and 10 for all the time.
In the past month, have you had a normal digestive routine, with no irregularities such as diarrhoea and constipation? 1 for never, and 10 for nothing wrong with my bowels.
Have you bitten your nails, fidgeted with your phone, or showed any nervous behaviours more frequently in the past two weeks? 1 for 1 day or less, 10 for 10 days or more.

HTML 获取测试文件

{%extends "base.html" %}
{% block title %}Take the Test{% endblock %}
{% block content %}
<head>
  <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-glyphicons.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
    <div class="row vh-100">
        <div class="col-1"></div>
        <div class="col-6">
            <h3>About The Test</h3>
            <p class="blue">This test will ask you if you seem to have any of the different symptoms of burn out, anxiety and extreme
                stress. Consider these questions as abnormal things you usually don’t do – like if you usually
                procrastinate and know it’s part of your personality, think if you have procrastinated more than usual.
                This test has been designed for teenagers, but is suitable for all ages. </p>
        </div>
        <div class="col-1"></div>
        <div class="col-3">
            <i class="glyphicon glyphicon-star" aria-hidden="true"></i><p class="blue">Test questions</p>
            <i class="glyphicon glyphicon-star-empty" aria-hidden="true"></i><p class="blue">More test questions</p>
            <i class="glyphicon glyphicon-star-empty" aria-hidden="true"></i><p class="blue">Your Results</p>
        </div>
        <div class="col-1"></div>
    </div>
    <div class="row vh-500">
        <div class="col-2"></div>
        <div class="col-8">
          <form action='/secondtestpage' method='POST'>
            <ol>
                {% for qnum,qtext in enumerate(q) %}
                    <li>{{qtext}}</li>
                    <label>{% for anum,atext in enumerate(answers) %}
                    {{atext}} <input type='radio' value='{{anum}}' name="question{{qnum}}"/>
                        {% endfor %}</label>
                {% endfor %}
                <input type="submit" value=" Next Page "/>
            </ol>
          </form>
        </div>
        <div class="col-2"></div>
    </div>
</div>
</body>
{% endblock %}

出现的错误

burn_out = calculate(firstquestions, 1, 5)
File "/Users/arimulligan/PycharmProjects/pythonProject1/hello.py", line 47, in calculate
    return render_template("takethetest.html", q=firstquestions, answers=questlist)
 
 
def calculate(first_list, firstq, lastq):
    for word in first_list:
        answered = request.form[word]
        mental_issue = 0
        if first_list.index(word) >= firstq and first_list.index(word) <= lastq:
            if first_list.index(word) % 2 != 0:
                mental_issue += int(answered) * 10
            elif first_list.index(word) % 2 == 0:
File "/Users/arimulligan/PycharmProjects/pythonProject1/venv/lib/python3.9/site-packages/werkzeug/datastructures.py", line 377, in __getitem__
raise exceptions.BadRequestKeyError(key)
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand. KeyError: 'Over the past month, have you been procrastinating more than ever? 1 for nope, 10 for yes too much!'

如果您想了解有关此的任何其他信息,请随时询问!如果我的代码很乱,请提前道歉。

标签: pythonhtmlformsfor-looppython-requests

解决方案


This should generate usable HTML. Then, your secondtestpage will receive elements like question0 with a value of 1 for answer #1 to question #0. Add 1 to those if you want.

        <form action='/secondtestpage' method='POST'>
                <ol>
                    {% for qnum,qtext in enumerate(q) %}
                        <li>{{qtext}}</li>
                        <label>{% for anum,atext in enumerate(answers) %}
                        {{atext}} <input type='radio' value='{{anum}}' name="question{{qnum}}"/>
                            {% endfor %}</label>
                    {% endfor %}
                    <input type="submit" value=" Next Page "/>
                </ol>
            </form>

推荐阅读