繁体   English   中英

Flask-RESTful如何add_resource并传递非全局数据

[英]Flask-RESTful how to add_resource and pass it non-global data

此处发布Flask-RESTful示例应用程序中, 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_argsresource_class_kwargs ,用于将参数传递给构造函数。 来源

所以你可以拥有一个资源:

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__)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM