pythonmarshmallowflask-smorest

Is there a way to pre-define validators that can be used multiple times?


I'm working on an API based flask app with flask-smorest and marshmallow validations. The issue I'm running into, is that many api endpoints require the same type of data, and I don't want to continually copy/paste the same validations over and over. Something like below would happen....

from marshmallow import Schema, fields, validate

class api1():

    class input1(Schema):
        request_ number = fields.Str(metadata={'description': 'Request Number', 'example':'REQUEST12345'}, validate=validate.Regexp(regex=r"^REQUEST\d{3,9}$", error="Input string didn't match required format - REQUEST12345"))   
        
class api2():

    class input1(Schema):
        request_ number = fields.Str(metadata={'description': 'Request Number', 'example':'REQUEST12345'}, validate=validate.Regexp(regex=r"^REQUEST\d{3,9}$", error="Input string didn't match required format - REQUEST12345"))       

What I want to do is create some sort of function or class BEFORE I define every api field/schema that I could recall.

Below is the idea, though I don't believe it works.

from marshmallow import Schema, fields, validate

class repetative_validators():
    request_number = validate.Regexp(regex=r"^REQUEST\d{3,9}$", error="Input string didn't match required format - REQUEST12345"))

class api1():

    class input1(Schema):
        request_ number = fields.Str(metadata={'description': 'Request Number', 'example':'REQUEST12345'}, validate=repetative_validators().request_number)
        
class api2():

    class input1(Schema):
        request_ number = fields.Str(metadata={'description': 'Request Number', 'example':'REQUEST12345'}, validate=repetative_validators().request_number) 

I was able to successfully test creating my own function for validation as described here, but was hoping to use the built in validators.

from marshmallow import Schema, fields, validate, ValidationError
import re

def validate_request_number(value):
    if not re.match(r"^REQUEST\d{3,9}$"):
        raise ValidationError("Input string didn't match required format - REQUEST12345")
        
class api1():

    class input1(Schema):
        request_ number = fields.Str(metadata={'description': 'Request Number', 'example':'REQUEST12345'}, validate=validate_request_number)
        
class api2():

    class input1(Schema):
        request_ number = fields.Str(metadata={'description': 'Request Number', 'example':'REQUEST12345'}, validate=validate_request_number)        

If anyone can link to appropriate documentation or an example that would be helpful. I haven't found anything like this in the marshmallow docs yet


Solution

  • I posted this also on the marshmallow github page, and was able to get a good response there.

    https://github.com/marshmallow-code/marshmallow/issues/2829

    from marshmallow import Schema, fields, validate
    
    class RequestNumber(fields.String):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, metadata={'description': 'Request Number', 'example':'REQUEST12345'}, validate=validate.Regexp(regex=r"^REQUEST\d{3,9}$", error="Input string didn't match required format - REQUEST12345")), **kwargs)
    
    
    class Api1():
    
        class Input1(Schema):
            request_number = RequestNumber()