7

I am trying to upload a file and well as take an input from the user in json format using Swagger UI. I have written the below code for the same.

upload_parser = api.parser()
upload_parser.add_argument('file', location='files',
                       type=FileStorage, required=True)

type = api.model("tax", {
"tax_form": fields.String()})

@api.route('/extraction')
@api.expect(upload_parser)
class extraction(Resource):
@api.expect(type)
def post(self):

    tax_form= api.payload # json input string
    print(tax_form['tax_form'])
    args = upload_parser.parse_args() # upload a file
    uploaded_file = args['file']
    output = func_extract(uploaded_file,tax_form['tax_form'])
    return output, 201

When i run the above individually for eg, if i only upload a file or only take an input from user, the code works but if i do them together. tax_from returns None value, it does not take what I am inputting as json value via Swagger UI.

2 Answers2

5

I got the issue solved. Used reqparse for inputting the argument. See the code snippet as below

upload_parser = api.parser()
upload_parser.add_argument('file', location='files',
                   type=FileStorage, required=True)

parser = reqparse.RequestParser()
parser.add_argument('tax_form', required = True)

@api.route('/extraction')
@api.expect(upload_parser)

class extraction(Resource):
@api.expect(parser)

def post(self):
    """
    extract the content
    """
    args1 = parser.parse_args()
    tax_form = args1['tax_form']
    print(tax_form)
    args = upload_parser.parse_args()
    uploaded_file = args['file']
    output = func_extract(uploaded_file,tax_form)
    return output, 201
  • 1
    This is bypassing the issue. Instead of using a json body payload, the solution is using arguments in the url. Do you have a different solution that you're using today? – RaamEE Dec 23 '18 at 16:29
0

I recommend using list of models and parsers in api.expect with validate=True(if required). This will remove the dependency of defining the expected query parameter (in your case) in the class level as you may have GET/PUT/DELETE API on the same route which may not even need this parameter.

Have modified your code to understand better:

upload_parser = api.parser()
upload_parser.add_argument('file', location='files',
                           type=FileStorage, required=True)

tax_type = api.model("tax", {"tax_form": fields.String()})

@api.route('/extraction')
class extraction(Resource):
    @api.expect(tax_type, upload_parser, validate=True)
    def post(self):
        tax_form= api.payload # json input string
        args = upload_parser.parse_args() # upload a file
        uploaded_file = args['file']
        output = func_extract(uploaded_file,tax_form['tax_form'])
        return output, 201

    # This METHOD is now independent of your POST data expectations
    def get(self):
        output = {} # Some JSON
        return output, 200

Also, please avoid using python reserved keywords like 'type' as variables.

Hope this helps ..!!

Community
  • 1
  • 1
  • 1
    Hi @sawan - this way didn't work for me. I was getting the following error: { "errors": { "": "None is not of type 'object'" }, "message": "Input payload validation failed" } – Riley Hun Jan 18 '21 at 18:02