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

In the Flask-RESTful application posted here , the collection is a global variable. TODOS

After registering a Todo Resource :

api.add_resource(Todo, '/todos/<string:todo_id>')

Methods Todoaccess a global variable TODOSwhen processing web requests.

Instead, I want to create an instance of the API inside the class and pass the collection TODOS, which is a class variable, not a global variable.

When using Flask-RESTful , how to properly enable Resource class methods to access the variable provided by the calling class without using global variables

+4
source share
3 answers

It seems that I did not understand you for the first time, you can simply use classmethodto create your API. Then add it as a resource

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()
+4
source

add_resourceaccepts two arguments, resource_class_argsand resource_class_kwargs, used to pass arguments to the constructor. ( source )

So, you may have a resource:

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

You can enter the required dependency in TodoNext like this:

smart_engine = SmartEngine()

api.add_resource(TodoNext, '/next',
    resource_class_kwargs={ 'smart_engine': smart_engine })
+2
source

@Greg init:

Todo Resource flask-restful api:

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':                  'todo_repository' 'ITodoRepository'.                  factory

edit: api ( IoC)

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

All Articles