Open AbdoDabbas opened 5 years ago
I tried to apply this with no luck: https://aviaryan.com/blog/gsoc/restplus-validation-custom-fields
I don't know how to do a custom validator, but you can use "pattern" to validate the string:
api.model('a_name', { 'email': fields.String(required=True, pattern='\S+@\S+.\S+') })
I hope it helps
@AbdoDabbas , reading what you implemented, and your described problem, did you implement the last step? In the example you posted, they created another function, validate_payload()
. While the description is incomplete, I inferred that this method was then called on each endpoint after serializing the payload. something like:
@route("/test")
class MyResource(Resource):
@api.expect(MY_MODEL, validate=False)
def post(self):
payload = api.payload
validate_payload(payload, MY_MODEL)
This is based on the code in the flask_restplus Resource
class: https://github.com/noirbizarre/flask-restplus/blob/master/flask_restplus/resource.py#L75
I'm not having good luck on peeking where validate_payload
is called though.
@JBarrioGarcia I tried your way, the problem now is the error message is strange, it says:
'string' does not match '\\\\S+@\\\\S+.\\\\S+'
If 'string' can be resolved using the "title", I didn't find how to replace the pattern in the message to be something I want. So the idea is, is there a way to replace the error message?
+1. the pattern=...
solution works, but it gives a really ugly message and confuses users
there's a similar problem here, but it's an odd-ball solution.
This thread describes exactly the expected behaviour of a custom field, but for whatever reason it's not working. Just wondering if there's been any work done on this?
I was able somehow to work around this by doing two things:
pydantic
throws and throw them again using the same schema that flask uses when you define your api.model
. Here:
https://gist.github.com/AbdoDabbas/54f1f0ad2312e95e5a43da7f062ef577
you can find a snippet code of what I mean.
Maybe pydantic
integration can be built inside flask-restplus
, I was going to do it specifically with directives (response
, expect
), but didn't know how to override it or change.
@AbdoDabbas It seems you're doing validation after flask-restplus already had a crack at it and passed it. You can definitely do validation inside the endpoints, but that pollutes your routes and creates a fractured logic - some validation happens before, some after. Besides, the @api.expect
with validate=True
should do exactly that already.
@AbdoDabbas It seems you're doing validation after flask-restplus already had a crack at it and passed it. You can definitely do validation inside the endpoints, but that pollutes your routes and creates a fractured logic - some validation happens before, some after. Besides, the
@api.expect
withvalidate=True
should do exactly that already.
Actually I need to do it before, but using api model validation way will not give me what I need and it's limited as you saw in the previous comments.
I think it may work better using the before_request
decorator, I will try it later.
@AbdoDabbas I created a PR addressing this issue in a more standardized way (imho). If you don't want to wait, you can just update your own copy of the flask_restplus/model.py
file and use it exactly the way you described in your post. Only difference, instead of returning False, you'd have to raise Exception
to fail validation.
@andreixk
Actually I'm raising an exception already:
https://gist.github.com/AbdoDabbas/54f1f0ad2312e95e5a43da7f062ef577
This link explains the idea, we can use it in flask-restplus I think.
Is there a way to write a validator for a custom field type that I can use in the API model (in except decorator). I mean like this:
I tried to inherit from
fields.String
and did it like: