flask-restx icon indicating copy to clipboard operation
flask-restx copied to clipboard

Allow multiple marshal_with decorators

Open MajorDallas opened this issue 4 years ago • 4 comments

Is your feature request related to a problem? Please describe. Using @namespace.marshal_with multiple times on one method results in only the outer-most marhal_with's model being used. The only workaround is to instead use @namespace.response and explicitly call marshal within a mess of control flow statements.

Describe the solution you'd like I would like to get rid of the many if-blocks and replace them with marshal_with decorators that can dispatch to the correct model based on status code.

# instead of this:
    @ns.response(200, ok_model)
    @ns.response(400, validation_err)
    @ns.response(500, internal_err)
    def post(self):
        result = do_stuff_on(request.json)
        if (status := result[1]) == 200:
            return marshal(result.content, ok_model), result[1]
        elif status == 500:
            return marshal(result.content, internal_err), result[1]
        elif status == 400:
            return marshal(result.content, validation_err), result[1]
        # This gets REAL messy if you can get any of a dozen different outcomes that all need 
        # distinct models, or if the result state is communicated in a more rich/complex way 
        # or not at all.

# this:
    @ns.marshal_with(ok_model, code=200)
    @ns.marshal_with(validation_err, code=400)
    @ns.marsnal_with(internal_err, code=500)
    def post(self):
        return do_stuff_on(request.json)

# or even this:
    @ns.marshal_with({200: ok_model, 400: validation_err, 500: internal_err})
    def post(self):
        return do_stuff_on(request.json)

I don't think the current closure-based approach can be easily hacked to allow this. My first thought was to use a mapping of model names to marshalling.marshal_with instances, but I'm not sure how to change what the closure returns or how the handler then gets called. Second thought was singledispatch, but since that can't dispatch on Literal types as of Py38 you'd need a class for every HTTP status code... (or a class factory).

MajorDallas avatar Jul 01 '21 21:07 MajorDallas

We definitely need this feature.

Enno-H avatar Jul 26 '21 09:07 Enno-H

this is a MUST feature

yanivakiva avatar Sep 29 '21 09:09 yanivakiva

Is there any solution or workaround to this in 2023?

mhetreramesh avatar Apr 14 '23 15:04 mhetreramesh