【问题标题】:Using Flask Restful as a Blueprint in Large Application在大型应用程序中使用 Flask Restful 作为蓝图
【发布时间】:2016-07-19 02:26:13
【问题描述】:

我正在尝试以适用于其他蓝图的模式将 Flask restful 用作蓝图。我不断收到以下错误消息

我收到以下错误消息

AttributeError: 'Blueprint' 对象没有属性 'add_resource'

我的项目设置如下:

文件夹结构

├── app
│   ├── __init__.py
│   ├── api
│   │   ├── __init__.py
│   │   └── routes.py
│   ├── main
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   └── views.py
│   └── templates
│       ├── base.html
│       └── home.html
├── config.py
├── manage.py
└── requirements.txt

__init__.py

from flask import Flask
from flask_restful import Api
from flask_bootstrap import Bootstrap
from config import config
bootstrap = Bootstrap()
api = Api()

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)

    bootstrap.init_app(app)
    api.init_app(app)

    from .main import main as main_blueprint
    from .api import api as api_blueprint
    app.register_blueprint(main_blueprint)
    app.register_blueprint(api_blueprint)
    return app

api/__init__.py

from flask import Blueprint

api = Blueprint('api', __name__)

from . import routes

api/routes.py

from flask_restful import Resource
from . import api

class TodoItem(Resource):
    def get(self, id):
        return {'task': 'Say "Hello, World!"'}

api.add_resource(TodoItem, '/todos/<int:id>')

我做错了什么??

【问题讨论】:

  • 你有一个变量和一个名为api的包。我认为那会让你绊倒。您从api/__init__.py 导入api 蓝图,而不是__init__.py 中的api 实例。

标签: flask flask-restful


【解决方案1】:

如果您按照https://flask-restful.readthedocs.io/en/0.3.5/intermediate-usage.html的指示进行操作

这里的重点是创建一个 Flask 蓝图实例并将其传递给 flask-restfuls 的 Api 类的新实例。

最后,确保在你的 create_app 函数中注册 flask-restful api 蓝图:app.register_blueprint(api_bp)

from flask import Flask, Blueprint
from flask_restful import Api
from flask_bootstrap import Bootstrap
from config import config

bootstrap = Bootstrap()
api_bp = Blueprint('api', __name__)
api = Api(api_bp)

def create_app(config_name):
   app = Flask(__name__)
   app.config.from_object(config[config_name])
   config[config_name].init_app(app)

   bootstrap.init_app(app)

   from .users import main as users_blueprint
   from .blogs import main as blogs_blueprint

   # blueprints for blogs & users
   app.register_blueprint(users_blueprint)
   app.register_blueprint(blogs_blueprint)
   app.register_blueprint(api_bp)
   
   return app

另外请注意,您不再需要注册api.init_app(app)

【讨论】:

  • 如果我们想通过 api 使用多个蓝图怎么办?
  • @darmendarizp 我已经更新了示例,使使用多个蓝图更加清晰。
  • 谢谢,但我的意思是,如果我们也想做Api(users_blueprint)Api(blogs_blueprint) 之类的事情怎么办?这样每个蓝图都可以使用flask_restful,但使用“Api 的单个实例”。我找不到这方面的例子。
  • 您的所有路由,包括用户和博客都将使用 Flask-Restful API 的同一个实例。使用api,您可以使用add_resource 方法添加所有资源:api.add_resource(BlogsView) & api.add_resource(UsersView)
【解决方案2】:

您遇到了麻烦,因为您将蓝图命名为 api,同时还使用了来自 flask_restfulapi 对象。在您的routes.py 中,您从api/__init__.py 显式导入api,这是一个Blueprint 对象。您不能将add_resource 调用到Blueprint 对象,只能调用来自flask_restfulApi 对象。

如果您将导入更改为:

from .. import api

您将导入正确的对象。我仍然建议您更改您的蓝图名称以避免这种混淆。

【讨论】:

  • 谢谢,这修复了导入错误,但是当我转到 /todos/1 时得到 404
【解决方案3】:

如果您想拥有基于资源的子模块(如 your /api)...

例如:文件夹结构

├── app
│   ├── __init__.py
│   ├── foo
│   │   ├── __init__.py
│   │   └── routes.py
│   ├── boo
│   │   ├── __init__.py
│   │   └── routes.py
├── config.py
├── manage.py

... 并使用 url_prefix 注册他们的蓝图,以免在每个添加的资源中重复公共部分。在每个模块中创建新的 Api 实例并将蓝图传递给它。

foo/__init__.py

from flask import Blueprint                            
from flask_restful import Api
                                                       
foo_bp = Blueprint('foo', __name__, url_prefix='/foo') 
foo_api = Api(foo_bp)  
                                                                                     
from . import routes 

在路由中导入 foo_api 并为其添加资源

foo/routes.py

from flask_restful import Resource
from . import foo_api

class TodoItem(Resource):
    def get(self, id):
        return {'task': 'Say "Hello, World!"'}

foo_api.add_resource(TodoItem, '/todos/<int:id>')
                          

然后在主应用程序 __init__.py 中导入模块蓝图并注册它。您甚至不需要添加“主”应用程序蓝图。如果您要从主应用程序 __init__ 导入 api,那么您不能使用其自己的参数(如 url_prefix)注册每个蓝图。

__init__.py

from flask import Flask
from config import config

def create_app(config_name):
   app = Flask(__name__)
   app.config.from_object(config[config_name])
   config[config_name].init_app(app)

   from .foo import foo_bp
   from .boo import boo_bp

   app.register_blueprint(foo_bp)
   app.register_blueprint(boo_bp)

   return app

您可以在注册蓝图上设置 url_prefix(它具有优先级)或在创建时设置。要检查路线,您可以打印 app.url_map

【讨论】:

    猜你喜欢
    • 2017-05-27
    • 1970-01-01
    • 2019-07-26
    • 2017-06-17
    • 1970-01-01
    • 2018-10-18
    • 2012-10-15
    • 1970-01-01
    相关资源
    最近更新 更多