Search code examples
pythonpostflaskpayloadflask-restplus

How to validate date type in POST payload with flask restplus?


Consider the following:

from flask import Flask
from flask_restplus import Api, Resource, fields

app = Flask(__name__)
api = Api(app)
ns = api.namespace('ns')

payload = api.model('Payload', {
    'a_str': fields.String(required=True),
    'a_date': fields.Date(required=True)
})

@ns.route('/')
class AResource(Resource):

    @ns.expect(payload)
    def post(self):
        pass

If I POST {"a_str": 0, "a_date": "2000-01-01"} I get 400 as expected, because a_str is not a string. However, when I POST {"a_str": "str", "a_date": "asd"} I don't get 400. Here I would like to also get 400, because "asd" is not a common date format.

I looked into the Date class doc and I see that there is a format and a parse method which should check whether the string is in a common date format. However, they do not seem to be called here.

Is there another way how to do this? Currently I am validating the date format by hand, but it seems that fask restplus should be able to do it for me.


Solution

  • As @andilabs mentions, it really weird to define expected payload twice. You can define expected payload by using only RequestParser as so:

    from flask import Flask, jsonify
    from flask_restplus import Api, Resource, fields, reqparse, inputs
    
    app = Flask(__name__)
    api = Api(app)
    ns = api.namespace('ns')
    
    parser = reqparse.RequestParser()
    parser.add_argument('a_str', type=str)
    parser.add_argument('a_date', type=inputs.datetime_from_iso8601, required=True)
    
    
    @ns.route('/')
    class AResource(Resource):
    
        @ns.expect(parser)
        def get(self):
    
            try:  # Will raise an error if date can't be parsed.
                args = parser.parse_args()  # type `dict`
                return jsonify(args)
            except:  # `a_date` wasn't provided or it failed to parse arguments.
                return {}, 400
    
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    Test by using curl:

    $ curl -XGET -H "Content-type: application/json" -d '{"a_str": "Name", "a_date": "2012-01-01"}' 'http://127.0.0.1:5000/ns/'
    {
      "a_date": "Sun, 01 Jan 2012 00:00:00 GMT", 
      "a_str": "Name"
    }