I'm trying to validate all data being sent to my api. My url structure contains a variable within it, /api/v2/users/<string:username>/collections/
, as well as actual query string parameters, all of which need to be passed through validation.
The full url looks like this:
https://127.0.0.1:5000/api/v2/users/<string:username>/collections/?page=5&per_page=10
The two variables that need to be validated are: username
page
, and per_page
. The easy solution would be to change my url structure, but I'm wondering if it's possible to accomplish what I need and keep the simplicity that I currently have without adding additional validation within my resource class. If it's possible, how do you do it?
class UserCollections(Resource):
@use_args({
'username': fields.Str(
required=True,
validate=username_length,
error_messages=dict(
required='Username is required.',
validator_failed='Username can be between 3 and 25 characters.',
)
),
'page': fields.Int(
#required=True,
missing=1,
validate=feed_minmax_pages,
error_messages=dict(
validator_failed='Maximum number of pages reached.',
)
),
'per_page': fields.Int(
#required=True,
missing=5,
validate=validate.Range(min=5,max=25),
error_messages=dict(
validator_failed='Test number of pages reached.',
)
),
}, locations=('query',))
def get(self, args, username):
print(args)
print(username)
return default_schema(
data={},
http_status=200
)
When I run the code, I get a validation error for username
because it doesn't exist in the args.
After poking around for a while I came across the solution, which I now see in the webargs flaskparser documentation
This can easily be used in addition to other use_args location
params within the arguments. It appears that the request method function get
, post
, etc still requires that you pass in that url variable. In my case it was <username>
.
class UserCollections(Resource):
@use_args({
'username': fields.Str(
location='view_args',
required=True,
validate=username_length,
error_messages=dict(
required='Username is required.',
validator_failed='Username can be between 3 and 25 characters.',
)
),
'page': fields.Int(
location='query',
missing=1,
validate=feed_minmax_pages,
error_messages=dict(
validator_failed='Maximum number of pages reached.',
)
),
'per_page': fields.Int(
location='query',
missing=5,
validate=validate.Range(min=5,max=25),
error_messages=dict(
validator_failed='Test number of pages reached.',
)
),
})
def get(self, args, username):
print(args) # access with args['username']
print(username) # would be nice to not have a second of the same var
return default_schema(
data={},
http_status=200
)