当 Flask 应用程序服务器与应用程序所需的其他文件放在文件夹中时获取“"Not Found The requested URL was not found on the server"

Getting ""Not Found The requested URL was not found on the server" when Flask app server is placed in folder with other files needed for application

对于我正在制作的程序,我需要能够向本地服务器发送 POST 请求以控制游戏。我正在使用 Flask 运行 所有这些。

app.py 包含设置服务器和接收请求的 Flask 代码。当 app.py 在任何文件夹之外并且只是在我的桌面上时,它就可以正常工作。在文件夹中时,其组织如下所示,页面不起作用,并给出 404 错误。当我转到本地主机地址时,它告诉我找不到 URL。

我在下面更详细地概述了这个问题。我包括文件夹组织、我在终端和服务器中收到的错误、我如何 运行 代码以及我在每个文件中编写的代码。我不确定是什么导致了这个问题。

  1. 我的文件组织如下:
game/
  game.py
  app/
    __init__.py
    app.py
  1. 当我运行终端程序时,我cd进入app文件夹,然后在命令行中输入以下命令:

    • 出口FLASK_APP=game.py
    • 烧瓶运行
  2. 这是当我转到 app.py 应该创建的本地主机时在终端中打印的内容。我在它说它不存在的地方加粗了:

     * Debug mode: off
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    127.0.0.1 - - [26/Dec/2019 23:29:28] "GET / HTTP/1.1" 404 -
    
  3. 在本地主机网页上,我收到以下错误:

    "Not Found The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."

  4. 文件内容:

    • game.py
    from app import app
    
    • __init__.py
    from flask import Flask
    
    app = Flask(__name__)
    
    • app.py
    from flask import Flask, request 
    
    app = Flask(__name__) #create the Flask app
    
    @app.route('/', methods=['POST','GET'])
    def form():
        if request.method == 'POST':
            concentrated = request.form.get('concentrated')
            return '''The person is concentrated? {}'''.format(concentrated)
    
         return '''<form method="POST">
            Concentrated <input type="text" name="concentrated">
            <input type="submit">
            </form>'''
    
    
    if __name__ == '__main__':
        app.run(debug=True, port=5000)
    

我看了这个问题,但它似乎对我的情况没有帮助:Why does localhost:5000 not work in Flask?

app/__init__.py:

from flask import Flask

app = Flask(__name__)

from .app import *

app.py:

from flask import Flask, request 

from app import app

@app.route('/', methods=['POST','GET'])
def form():
  if request.method == 'POST':
      concentrated = request.form.get('concentrated')
      return '''The person is concentrated? {}'''.format(concentrated)

     return '''<form method="POST">
      Concentrated <input type="text" name="concentrated">
      <input type="submit">
      </form>'''

在game.py中应该是:

from app import app

if __name__ == '__main__':
    app.run(debug=True, port=5000)

它看起来像 has already solved your problem, but I wanted to explain the cause of the original problem and offer my own solution that does not use import * (see Why is “import *” bad? and the PEP8 guidelines on imports 说“通配符导入(from <module> import *) 应该避免,因为它们使命名空间中存在哪些名称不清楚,使两个读者感到困惑和许多自动化工具。").

问题

鉴于此:

game
├── app
│   ├── __init__.py  # instantiates app = Flask(__name__)
│   └── app.py       # also instantiates app = Flask(__name__) 
└── game.py

这里的 app 文件夹被视为 因为 __init__.py 文件(参见 Packages 部分142=] 文档)。 __init__.py 可以是空的,但是如果你把一些初始化代码放在那里(比如 app Flask 实例的实例化),它将在 Python 导入 app 包。

您可以通过侵入 Flask 配置并添加 "whoami" 属性来尝试:

app/__init__.py

app = Flask(__name__)
app.config.update({"whoami": "In app/__init__.py"})

app/app.py

app = Flask(__name__)  
app.config.update({"whoami": "In app/app.py"})

# rest of your code

game.py

from app import app

print(app.config["whoami"])

运行

(运行从游戏文件夹中下载)

game$ export FLASK_APP=game.py
game$ flask run
 * Serving Flask app "game.py"
...
In app/__init__.py
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

请注意,导入的 app 是来自 __init__.py 的,它不包含方法 form,它应该为 / URL。这就是为什么当您尝试访问 http://127.0.0.1:5000/ 时,Flask 会引发一个错误,指出未找到所请求的 URL (/)。

此行为类似于所谓的“隐藏”,其中 __init__.py 中的 app 隐藏了 app.py 中的 app。事实上,app.py中的app在这里从来没有用过。

解决方案

一样,只需将__init__.py文件保持为空即可。它的主要目的(针对你的情况)只是告诉 Python app 文件夹 实际上是一个 ,允许导入 from app import app.

app/init.py

# leave this empty

app/app.py

from flask import Flask, request

app = Flask(__name__)  #create the Flask app
app.config.update({"whoami": "In app/app.py"})

@app.route('/', methods=['POST', 'GET'])
def form():
    if request.method == 'POST':
        concentrated = request.form.get('concentrated')
        return '''The person is concentrated? {}'''.format(concentrated)
    elif request.method == 'GET':
        return '''<form method="POST">
        Concentrated <input type="text" name="concentrated">
        <input type="submit">
        </form>'''

if __name__ == '__main__':
    app.run(debug=True, port=5000)

game.py

from app.app import app

print(app.config["whoami"])

运行

(运行从游戏文件夹中下载)

game$ export FLASK_APP=game.py
game$ flask run
 * Serving Flask app "game.py"
...
In app/app.py
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [28/Dec/2019 09:23:05] "GET / HTTP/1.1" 200 -

注意这里的四件事。

  1. app/__init__.py 现在是空的。
  2. game.py 中的导入语句已更改。它现在读作“从应用程序包的应用程序模块中导入应用程序实例”。 app文件夹是“应用包”,app.py文件是“应用模块”,app = Flask(__name__)是“应用实例”。这是在 Python: from package.module import something 中导入内容的典型方式。如果您对所有“应用程序”感到困惑,您可能想要重命名其中的一些。
  3. 打印 "whoami" 属性现在可以正确显示 app 实例是来自 app/app.py 的实例,也就是具有您的实际路由方法的实例。
  4. 我将您 form 方法中的两个 return 语句更改为一个用于 GET 请求和一个用于 POST 请求,只是为了使其明确。

现在,当您转到 http://127.0.0.1:5000/ 时,它现在应该更正 / URL.

的工作