Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[QUESTION] There's a way to add a custom decorator to a class-based view? #261

Open
JesusFragoso opened this issue Oct 18, 2022 · 1 comment
Labels
question Further information is requested

Comments

@JesusFragoso
Copy link

I'm trying to do something like the following:

@cbv(users_router)
@ResponseHandler.class_decorator
class Users:

    controller = UserController()

    @users_router.post("/users", status_code=201)
    async def create_user(self, user_data: Dict, response: Response) -> Dict:
        return self.controller.create_user(**user_data)

    @users_router.get("/users/{user_id}", status_code=302)
    async def get_user(self, user_id: int, response: Response) -> Dict:
        return self.controller.obtain_user(user_id)

    @users_router.get("/users", status_code=302)
    async def get_all_users(self, response: Response) -> Dict:
        return self.controller.obtain_all_users()

The class_decorator decorator adds custom response for each one of the requests, but when I try to execute one of the services, then this error appears:

{"detail":[{"loc":["query","self"],"msg":"field required","type":"value_error.missing"}]}
@JesusFragoso JesusFragoso added the question Further information is requested label Oct 18, 2022
@JesusFragoso
Copy link
Author

The code for the decorator is the following:

class ResponseHandler:
    @staticmethod
    def custom_response(main_function: Callable) -> Callable:
        @wraps(main_function)
        async def handler_function(*args: Tuple, **kwargs: Dict) -> Dict:
            try:
                result, code = await main_function(*args, **kwargs)
            except tuple(SERVICE_EXCEPTIONS) as exception:
                ResponseHandler._modify_status_code(kwargs["response"], exception.code.value)

                return {
                    "exception_message": exception.message,
                    "code": exception.code,
                }
            except IntegrityError as exception:
                ResponseHandler._modify_status_code(kwargs["response"], 400)

                return {
                    "exception_message": exception._message(),
                    "code": 400,
                }

            return {"data": result, "status_code": code}

        return handler_function

    @staticmethod
    def _modify_status_code(response: Response, status_code: int) -> NoReturn:
        response.status_code = status_code
    
    @staticmethod
    def class_decorator(my_class):
        def wrapper(*args, **kwargs):
            members = list(filter(lambda member: "__" not in member[0], inspect.getmembers(my_class)))

            for name, method in members:
                setattr(my_class, name, ResponseHandler.custom_response(method))
        
            return my_class()
        
        return wrapper

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant