405:方法不允许。为什么我在 Flask 中收到此错误

405: Method Not Allowed. Why am I getting this error in Flask

我尝试了所有可能的方法并阅读了 SO 中的许多帖子。对于“不允许的方法”错误,我还没有任何解决方案。任何人都可以检查并让我知道我做错了什么吗?我很沮丧,因为我是 Flask 的新手,无法继续。

这是我的模板文件add_cars.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Datastore and Firebase Auth Example</title>
    <script src="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.js"></script>
    <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.4.0/firebase-ui-auth.css" />
    <script src="{{ url_for('static', filename='script.js') }}"></script>
    <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    <link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='navstyle.css') }}">
</head>
    <body>
    <div class="topnav">
        <a class="active" href="{{ url_for('root') }}">Home</a>
        <a href="{{ url_for('list_ev') }}">EV List</a>
        <a href="#contact">Contact</a>
        <a href="#about">About</a>
    </div>
    <h2>Add car details</h2>
    <div id="firebase-auth-container"></div>
    {% if user_data %}
    <p align="right">Email: {{ user_data['email'] }}</p>
    <button id="sign-out" hidden="true" style="float: right;">Sign out</button>
    <div id="login-info" hidden="true">
        <form action="/add_cars" method="post">
            Car name:<input type="text" value="" name="name_update"/><br/>
            Manufacturer:<input type="text" value="" name="manufacturer_update"/><br/>
            Year:<input type="number" value="" name="year_update"/><br/>
            Battery size:<input type="number" value="0.0" name="battery_update" step="any"/><br/>
            Range:<input type="number" value="" name="range_update"/><br/>
            Cost:<input type="number" value="" name="cost_update"/><br/>
            Power:<input type="number" value="" name="power_update" step="any"/><br/><br>
            <input type="submit" class="button-1" value="Add details" name="submit_button"/>
        </form>
        {% elif error_message %}
        <p>Error Message: {{ error_message }}</p>
    {% endif %}
    </div>
    <br>
<!--    <div>-->
<!--        <a href="{{ url_for('list_ev') }}" class="button-1">View all cars</a>-->
<!--    </div>-->

    <script src="https://www.gstatic.com/firebasejs/7.14.5/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-auth.js"></script>
    <script src="{{ url_for('static', filename='app-setup.js') }}"></script>

</body>
</html>

这是我的main.py

from flask import Flask, render_template, request, redirect, url_for
import google.oauth2.id_token
from google.auth.transport import requests
from google.cloud import datastore
import os, random
os.environ["GOOGLE_APPLICATION_CREDENTIALS"]="google_auth_json.json"

firebase_req_adapter=requests.Request()

app = Flask(__name__)
datastore_client = datastore.Client()

def store_time(email):
    entity = datastore.Entity(key = datastore_client.key('User', email, 'visit'))
    entity.update({'email' : email})
    datastore_client.put(entity)

def retrieveCarInfo(claims):
    entity_key = datastore_client.key('CarInfo', claims['email'])
    entity = datastore_client.get(entity_key)
    return entity

def createCarInfo(claims):
    entity_key = datastore_client.key('CarInfo', claims['email'])
    entity = datastore.Entity(key = entity_key)
    entity.update({
        'email': claims['email'],
        'name': claims['name'],
        'cars_list': []
    })
    datastore_client.put(entity)

def retrieveCars(car_info):
    car_ids = car_info['cars_list']
    car_keys = []
    for i in range(len(car_ids)):
        car_keys.append(datastore_client.key('car', car_ids[i]))
    cars_list = datastore_client.get_multi(car_keys)
    return cars_list

def createCarDetails(claims, new_car_string, new_man_string, new_yr_int, new_bt_float, new_rg_int, new_cost_int, new_pr_int):
    id = random.getrandbits(63)
    entity_key = datastore_client.key('car', id)
    entity = datastore.Entity(key = entity_key)
    entity.update({
        'name': new_car_string,
        'manufacturer': new_man_string,
        'year': new_yr_int,
        'battery_size': new_bt_float,
        'range': new_rg_int,
        'cost': new_cost_int,
        'power': new_pr_int,
    })
    datastore_client.put(entity)
    return id

def addcarToUser(car_info, id):
    car_keys = car_info['cars_list']
    car_keys.append(id)
    car_info.update({
        'cars_list': car_keys
    })
    datastore_client.put(car_info)

def deleteCars(claims, id):
    car_info = retrieveCarInfo(claims)
    car_list_keys = car_info['cars_list']
    car_key = datastore_client.key('Car', car_list_keys[id])
    datastore_client.delete(car_key)
    del car_list_keys[id]
    car_info.update({
        'car_info' : car_list_keys
    })
    datastore_client.put(car_info)

# All functions below to render data to templates

@app.route("/")
def root():
    id_token = request.cookies.get("token")
    error_message = None
    claims = None
    car_info = None
    cars = None
    if id_token:
        try:
            claims = google.oauth2.id_token.verify_firebase_token(id_token,
                                                                  firebase_req_adapter)
            store_time(claims['email'])
            car_info = retrieveCarInfo(claims)
            if car_info == None:
                createCarInfo(claims)
                car_info = retrieveCarInfo(claims)
                cars = retrieveCars(car_info)
        except ValueError as exc:
            error_message = str(exc)
    return render_template('index.html', user_data=claims, error_message=error_message,
                           car_info=car_info, cars=cars)
    # return render_template('index.html', user_data=claims, error_message=error_message)

@app.route("/add_cars", methods=['POST'])
def add_ev():
    # add ev's
    id_token = request.cookies.get("token")
    error_message = None
    claims = None
    car_info = None
    if id_token and  request.method=='POST':
        try:
            claims = google.oauth2.id_token.verify_firebase_token(id_token, firebase_req_adapter)
            car_info = retrieveCarInfo(claims)
            id = createCarDetails(claims,
                                  request.form['name_update'],
                                  request.form['manufacturer_update'],
                                  request.form['year_update'],
                                  request.form['battery_update'],
                                  request.form['range_update'],
                                  request.form['cost_update'],
                                  request.form['power_update'])
            addcarToUser(car_info, id)
        except ValueError as exc:
            error_message = str(exc)

    return redirect(url_for("add_ev"))
    # return render_template('add-cars.html', user_data=claims, error_message=error_message, car_info=car_info)

@app.route("/list")
def list_ev():
    # listing all ev's
    id_token = request.cookies.get("token")
    error_message = None
    claims = None
    car_info = None
    if id_token:
        try:
            claims = google.oauth2.id_token.verify_firebase_token(id_token,
                                                                  firebase_req_adapter)
            car_info = retrieveCarInfo(claims)
            if car_info == None:
                createCarInfo(claims)
                car_info = retrieveCarInfo(claims)
        except ValueError as exc:
            error_message = str(exc)
    return render_template('list_ev.html', user_data=claims, error_message=error_message, car_info=car_info)

@app.route('/delete_cars/<int:id>', methods=['POST'])
def deleteCarFromUser(id):
    id_token = request.cookies.get("token")
    error_message = None
    if id_token:
        try:
            claims = google.oauth2.id_token.verify_firebase_token(id_token, firebase_req_adapter)
            deleteCars(claims, id)
        except ValueError as exc:
            error_message = str(exc)
    return redirect('/')

if __name__=='__main__':
    app.run(host='127.0.0.1', port=8082, debug=True)

更新:

当您重定向时,您最终会向您的端点发送一个 GET 请求,但是您的端点仅支持 POST。 因此,您应该创建一个不同的端点,它支持 GET 并托管您在上面引用的模板。然后模板的形式可以发送一个POSTadd_ev端点,然后add_ev重定向到新的GET端点并关闭循环。

之前的建议:

您可以尝试将 GET 作为支持的方法添加到以下端点吗?

@app.route("/add_cars", methods=['GET', 'POST'])
def add_ev():
    # add ev's
    ...

您需要在 add_ev 中添加对 GET 的支持,并将重定向限制为仅 POST (否则您将以无限循环结束)即类似于

@app.route("/add_cars", methods=['GET','POST'])
def add_ev():
    ...
    if request.method == 'POST':
        return redirect(url_for("add_ev"))
    elif request.method == 'GET':
        return render_template('add_cars.html')