marshmallow-code / flask-smorest

DB agnostic framework to build auto-documented REST APIs with Flask and marshmallow
https://flask-smorest.readthedocs.io
MIT License
634 stars 72 forks source link

How to allow alternative response schema eg. for 4xx status codes #663

Open koko236 opened 1 week ago

koko236 commented 1 week ago

I have endpoints defined with Marshmallow schemas, eg.:

    @blp.response(200, ProjectSchema)
    def get(self, project_uuid):
        '''
        Get project by uuid
        '''
        project = projects_service.get_project_by_id(project_uuid)
        if project is None:
            return {'message': 'Project not found'}, 404
       # ...rest of the function...

The problem is when I return 404 the json is empty because (I assume) 'message' key gets stripped by ProjectSchema. When I comment out @blp.response line I can get the message error as intended. I tried creating ErrorSchema:

class ErrorSchema(ma.Schema):
    '''
    Error schema
    '''
    message = ma.fields.String(required=True, metadata={'description': 'The error message'})

And alt_response as follows:

@blp.alt_response(404, schema=ErrorSchema(unknown=ma.EXCLUDE))

But it doesn't help. What is the correct way of handling such a scenario?

lafrech commented 3 days ago

Use abort.

This should work:

    from flask_smorest import abort
    from flask_smorest.error_handler import ErrorSchema

    @blp.response(200, ProjectSchema)
    # I woudn't bother documenting the 404 but if you want to do so, uncomment
    # @blp.alt_response(404, schema=ErrorSchema)
    def get(self, project_uuid):
        '''Get project by uuid'''
        project = projects_service.get_project_by_id(project_uuid)
        if project is None:
            abort(404)
            # I'd use the default message but you may override it
            # abort(404, message="Project not found")
       # ...rest of the function...
koko236 commented 1 day ago

Thanks a million! 👍🏿

So just to clarify, as discussed here: (https://github.com/marshmallow-code/flask-smorest/issues/166) the ONLY way to trigger alt response schema is by using abort method and if we return response then no matter what HTTP status is set the main response schema will be used, right?