Flask-RESTful如何add_resource并传递非全局数据
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask-RESTful如何add_resource并传递非全局数据相关的知识,希望对你有一定的参考价值。
在Flask-RESTful示例应用程序posted here中,TODOS
集合是一个全局变量。
在Todo
资源注册后:
api.add_resource(Todo, '/todos/<string:todo_id>')
当处理Web请求时,Todo
方法访问全局TODOS
变量。
相反,我想在类中实例化API并传递一个TODOS
集合,它是一个类变量而不是全局变量。
使用Flask-RESTful时,允许Resource类中的方法访问调用类提供的变量而不使用全局变量的正确方法是什么?
看起来我第一次不理解你,你可以使用classmethod
来构建你的API。然后将其添加为资源
from flask import Flask
from flask.ext.restful import Api
class SomeApi(Resource):
def get(self):
return self.response
@classmethod
def make_api(cls, response):
cls.response = response
return cls
class KillerApp(object):
def __init__(self):
self.app = Flask()
app_api = Api(self.app)
MyApi = SomeAPI.make_api({"key": "value"})
app_api.add_resource(MyApi, "/api/path")
def run(self)
self.app.run()
KillerApp().run()
add_resource
接受两个参数,resource_class_args
和resource_class_kwargs
,用于将参数传递给构造函数。 (source)
所以你可以拥有一个资源:
from flask_restful import Resource
class TodoNext(Resource):
def __init__(self, **kwargs):
# smart_engine is a black box dependency
self.smart_engine = kwargs['smart_engine']
def get(self):
return self.smart_engine.next_todo()
您可以将所需的依赖项注入TodoNext,如下所示:
smart_engine = SmartEngine()
api.add_resource(TodoNext, '/next',
resource_class_kwargs={ 'smart_engine': smart_engine })
基于@Greg回答我在init方法中添加了一个初始化检查:
为flask-restful api创建和调用Todo Resource类:
todo = Todo.create(InMemoryTodoRepository())
api.add_resource(todo, '/api/todos/<todo_id>')
Todo资源类:
from flask_restful import reqparse, abort, Resource
from server.ApiResources.DTOs.TodoDTO import TodoDTO
from server.Repositories.ITodoRepository import ITodoRepository
from server.Utils.Exceptions import InvalidInstantiationError
from server.Utils.GeneralUtils import member_exists
class Todo(Resource):
"""shows a single todo item and lets you delete a todo item
use the 'create' class method to instantiate the class
"""
def __init__(self):
if not member_exists(self, "todo_repository", of_type=ITodoRepository):
raise InvalidInstantiationError("Todo", "todo_repository", "ITodoRepository", "create")
self._parser = reqparse.RequestParser()
self._parser.add_argument('task', type=str)
@classmethod
def create(cls, todo_repository):
"""
:param todo_repository: an instance of ITodoRepository
:return: class object of Todo Resource
"""
cls.todo_repository = todo_repository
return cls
member_exists帮助方法:
def member_exists(obj, member, of_type):
member_value = getattr(obj, member, None)
if member_value is None:
return False
if not isinstance(member_value, of_type):
return False
return True
和自定义异常类:
class InvalidInstantiationError(Exception):
def __init__(self, origin_class_name, missing_argument_name, missing_argument_type, instantiation_method_to_use):
message = """Invalid instantiation for class '{class_name}':
missing instantiation argument '{arg}' of type '{arg_type}'.
Please use the '{method_name}' factory class method"""
.format(class_name=origin_class_name,
arg=missing_argument_name,
arg_type=missing_argument_type,
method_name=instantiation_method_to_use)
# Call the base class constructor with the parameters it needs
super(InvalidInstantiationError, self).__init__(message)
因此,尝试使用默认构造函数将最终获得此异常:
server.Utils.Exceptions.InvalidInstantiationError:类'Todo'的实例化无效:缺少类型为'ITodoRepository'的实例化参数'todo_repository'。请使用'create'工厂类方法
编辑:这可以用于使用依赖注入与flask-restful api资源类(有或没有IoC)
编辑2:
我们甚至可以更清洁并添加另一个帮助功能(准备导入):
def must_have(obj, member, of_type, use_method):
if not member_exists(obj, member, of_type=of_type):
raise InvalidInstantiationError(obj.__class__.__name__,
member,
of_type.__name__,
use_method)
然后在构造函数中使用它:
from server.Utils.GeneralUtils import must_have
class Todo(Resource):
def __init__(self):
must_have(self,
member="todo_repository",
of_type=ITodoRepository,
use_method=Todo.create.__name__)
以上是关于Flask-RESTful如何add_resource并传递非全局数据的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Flask-USER 管理保护 Flask-RESTful?
如何将 flask.url_for() 与 flask-restful 一起使用?
如何使用客户端上的“requests”模块和服务器上的“flask-restful”验证 https 请求的自签名证书(TLS1.2)