Flask:当我尝试访问索引时出现错误 404

时间:2021-02-18 10:04:17

标签: python flask routes http-status-code-404

当我使用 flask run 运行 Flask 服务器时,我在索引页中收到错误 404。

`${id}`
<块引用>

未找到

在服务器上找不到请求的 URL。如果您输入了网址 请手动检查您的拼写,然后重试。

  • 项目结构
 * Serving Flask app "sf.py"
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [18/Feb/2021 10:25:56] "GET / HTTP/1.1" 404 -
  • . ├── app │   ├── models.py │   ├── routes.py │   └── __init__.py ├── clients │   └── client.py ├── migrations ├── tests │   ├── conftest.py │   ├── test_models.py │   ├── test_client.py │   └── __init__.py ├── publisher.py ├── manage.py ├── run_client.py ├── requirements.txt └── sf.py
/sf.py
  • from app import create_app create_app()
/app/__init__.py
  • from flask import Flask from . models import db POSTGRES = { 'user': 'sf', 'pw': 'sf', 'db': 'sf', 'host': 'localhost', 'port': '5432', } def create_app(): app = Flask(__name__) app.config['DEBUG'] = True app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s' % POSTGRES app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) return app from app import routes
/app/routes.py

我需要使用 from app import create_app from app.models import Area, Sensor, Monitoring from flask import request, jsonify from flask.views import MethodView app = create_app() @app.route('/') def hello_world(): return 'Hello, World!' ... ,因为我需要 create_app() 使用该应用程序。

  • /clients/client.py
/clients/client.py

但是这样我得到了 404 错误。而且我不确定我是否正确使用了该应用程序。将应用程序和数据库会话分开会很好,可以在不关心应用程序配置的情况下测试模型和客户端(可能我需要为测试创建单独的配置?)。我错过了什么?

1 个答案:

答案 0 :(得分:3)

您正在创建 Flask() 对象的三个实例。一个在 sf.py 中创建,其他在 routes.pyclient.py 中创建。第一个用于为站点提供服务,因此没有您的路由,因为该路由已注册到在 routes.py 中创建的实例。 client.py 中的第三个实例是独立的,不会进一步改变,所以这里不是问题;更多内容见下文。

不要创建多个副本,至少不要更改一个上的注册并期望那些在另一个上可用。相反,使用 blueprints 注册您的视图,然后使用 Flask() 函数中的 create_app() 对象注册蓝图。这样,您可以将路线注册与创建 Flask() 对象分离,并且仍然可以集中注册您的路线。

在您的 routes.py 中,使用:

from app.models import Area, Sensor, Monitoring

from flask import Blueprint, request, jsonify
from flask.views import MethodView

bp = Blueprint('main', __name__)

@bp.route('/')
def hello_world():
    return 'Hello, World!'

# ...

然后在 create_app() 中导入该蓝图:

def create_app():
    app = Flask(__name__)

    app.config['DEBUG'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s' % POSTGRES
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    db.init_app(app)

    from . import routes
    app.register_blueprint(routes.bp)

    return app

您想在 create_app() 中进行导入的原因是,在大多数 Flask 应用程序中,您还将使用一个或多个通常在 create_app() 之外创建的 Flask 扩展,以便您的视图可以导入他们。如果您的 routes 模块在顶级导入到 routes,如果您尝试在 app.py 模块中导入这些对象之一,您将获得循环导入。

通过此更改(使用蓝图),您可以避免创建单独的 Flask() 实例,其中的注册用于服务您的站点的主实例不会看到。如果需要(例如,如果您需要使用 client.py 生成网址),即使您的 url_for() 进程现在也可以访问这些路由。

以下是我最近为客户构建的生产中 Flask 项目的示例,app.py 模块部分包含以下代码:

from flask import Flask
from flask_babel import Babel
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_security import Security, SQLAlchemyUserDatastore
from flask_sqlalchemy import SQLAlchemy


babel = Babel()
db = SQLAlchemy()
ma = Marshmallow()
migrate = Migrate()
security = Security()


_app_init_hooks = []
app_init_hook = _app_init_hooks.append


def create_app():
    app = Flask(__name__)

    for f in _app_init_hooks:
        f(app)

    return app


@app_init_hook
def _configure(app):
    """Load Flask configurations"""

    app.config.from_object(f"{__package__}.config")

    # optional local overrides
    app.config.from_pyfile("settings.cfg", silent=True)
    app.config.from_envvar("PROJECT_NAME_SETTINGS", silent=True)


@app_init_hook
def _init_extensions(app):
    """Initialise Flask extensions"""

    if app.env != "production":
        # Only load and enable when in debug mode
        from flask_debugtoolbar import DebugToolbarExtension

        DebugToolbarExtension(app)

    # Python-level i18n
    babel.init_app(app)

    # Database management (models, migrations, users)
    from .models import Role, User

    db.init_app(app)
    migrate.init_app(app, db)
    user_datastore = SQLAlchemyUserDatastore(db, User, Role)
    security.init_app(app, user_datastore)

    # Marshmallow integration (must run after db.init_app())
    ma.init_app(app)


@app_init_hook
def _setup_blueprints(app):
    """Import and initialise blueprints"""

    from . import users
    from .sections import BLUEPRINTS

    for blueprint in (*BLUEPRINTS, users.bp):
        app.register_blueprint(blueprint)

    return app

我已将各种组件分解为单独的功能以简化可读性和可维护性,有单独的蓝图用于不同的网站功能(这会推动 UI 中的一些自动化)。

在模块的顶部是几个 Flask 扩展,各种路由和其他模块需要访问这些扩展,而不必担心循环导入,因此蓝图在调用的 _setup_blueprints() 钩子函数内部单独导入create_app()

您在 create_app() 中使用 client.py 应该没问题,因为它不会向您希望在其他地方访问的 Flask() 实例添加任何新配置,并且大概client.py 在 Flask 网络服务器进程之外使用。但我个人只会将 create_app() 的结果设为您的 Client 实例的实例属性。您不需要全局变量,您只需要它在调用 add_reading() 时轻松访问数据库会话:

class CustomClient(Client):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs):
        # Create a Flask context so we can access the SQLAlchemy session
        self._app = create_app()

    def add_reading(self, reading):
        with self._app.app_context():
            db.session.add(reading)
            db.session.commit()

    # ...

如果 add_reading() 被频繁调用,您可以考虑将 app 设为 CustomClient() 的实例属性:

相关问题