2017-04-21 84 views
0

我知道我可以使用安装在模型的列一个验证,根据SQLAlchemy的documenation:SQLAlchemy的验证和额外的参数

def validate_phone(target, value, oldvalue, initiator): 
    "Strip non-numeric characters from a phone number" 

    return re.sub(r'(?![0-9])', '', value) 

# setup listener on UserContact.phone attribute, instructing 
# it to use the return value 
listen(UserContact.phone, 'set', validate_phone, retval=True) 

,但我想额外的参数传递给验证器,例如:

def check_range(target, value, oldvalue, initiator, begin, end) 
    if value in range(begin, end): 
     return value 
    else: 
     raise ValidationError() 

如何我必须在听者配置此验证器,这样它会接受额外的参数开始年底

回答

1

好吧,我通过向我的Column定义添加了一个参数(我已经定义了一个从Column继承来添加额外参数的RsColumn类)来解决这个问题,它包含一个带有验证器函数名称和可选参数的字典作为kwargs。

当我的应用程序启动时,它分析所有的模型,并检查是否有在列

validators=[ 
    { 
     "function": "myvalidatorname", 
     "kwargs": {"arg1": 1, "args": "someotherargument"} 
    }, 
    { ... } 
] 

-argument在列定义自定义验证。它在“set”上设置一个监听器,该监听器执行函数“execute_field_validations”,该函数再次解析字段中的所有“验证器”,并且如果给出它们,则可选地使用参数执行它们。

def check_positive(value, field): 
    # do stuff 
    pass 


def check_range(value, field, begin, end): 
    # do range checking 
    pass 


def execute_field_validations(model_instance, value, old_value, initiator): 
    """ 
    When a "set" event is given on a models field/column then execute 
    all the fields validators optionally with arguments as described 
    in the model's definition in db.models 

    for example VehicleType.loading_meters: 

     loading_meters = RsColumn(..., validators=[ 
      {"function": "check_positive"}, 
      {"function": "check_range", "kwargs": {"begin": 0, "end": 1000}} 
     ], ...) 
    """ 
    field = model_instance.__mapper__.columns[initiator.key] 

    for validator in field.validators: 

     try: 
      assert validator["function"] in globals(), \ 
       "Invalid validator '{0}' in column ".format(
        validator["function"] 
       ) 

      validator_function = globals()[validator["function"]] 

      if "kwargs" in validator: 
       validator_function(value, field, **validator["kwargs"]) 
      else: 
       validator_function(value, field) 

     except Exception as e: 
      raise ValueError()   

def configure_validators_on_individual_fields(base): 
    """ 
    Parse through all models and all defined columns/fields 
    and see if there are individual validators set on them. 
    If so add a listser for them on the "set"-event 
    """ 
    for table in base.metadata.tables: 
     for field in base.metadata.tables[table].columns: 
      if field.validators: 
       listen(
        getattr(
         get_class_by_tablename(table), 
         field.name 
        ), 
        "set", 
        execute_field_validations 
       )