2017-04-21 52 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 
       )