我不知道有什麼辦法讓formencode你問什麼。但是,由於這是Python,所以我們可以做的事情幾乎沒有限制。
您可以通過將打電話getActiveCodes
包裝在專門製作的課程中解決此問題。包裝類,RefreshBeforeContainsCheck
,將實行特殊的方法__iter__
和__contains__
提供必要的接口使用爲一個迭代的對象:
from formencode import Schema, validators, Invalid
class RefreshBeforeContainsCheck(object):
def __init__(self, func):
self._func = func
self._current_list = None
def __iter__(self):
print '__iter__ was called.'
#return iter(self._func()) # Could have refreshed here too, but ...
return iter(self._current_list)
def __contains__(self, item):
print '__contains__ was called.'
self._current_list = self._func() # Refresh list.
return item in self._current_list
我添加打印語句,使其更清晰之時如何表現運行。 RefreshBeforeContainsCheck
類然後可以在驗證器模式中使用,如
class ItemsEditSchema(Schema):
code = validators.OneOf(RefreshBeforeContainsCheck(getActiveCodes))
allow_extra_fields = True
。
它上面實現的方式,getActiveCodes
函數將被每次稱爲OneOf
驗證器執行item in list
測試(其中,我們的類充當list
),因爲這將導致RefreshBeforeContainsCheck.__contains__
被調用。現在,如果驗證失敗,OneOf
驗證程序會生成一條錯誤消息,列出list
的所有元素;該案件由我們的__iter__
實施處理。爲了避免在驗證錯誤時調用數據庫兩次,我選擇將「數據庫」結果列表緩存爲self._current_list
,但是否合適取決於您的需求。
我已經爲此創建了一個要點:https://gist.github.com/mtr/9719d08f1bbace9ebdf6,基本上創建了一個使用上面的代碼與以下代碼的示例。
def getActiveCodes():
# This function could have performed a database lookup.
print 'getActivityCodes() was called.'
codes = map(str, [1, 2, 3, 4])
return codes
def validate_input(schema, value):
print 'Validating: value: {!r}'.format(value)
try:
schema.to_python(value)
except Invalid, error:
print 'error: {!r}'.format(error)
print
def main():
schema = ItemsEditSchema()
validate_input(schema, {'code': '3'})
validate_input(schema, {'code': '4'})
validate_input(schema, {'code': '5'})
主旨的輸出是:
Validating: value: {'code': '3'}
__contains__ was called.
getActivityCodes() was called.
Validating: value: {'code': '4'}
__contains__ was called.
getActivityCodes() was called.
Validating: value: {'code': '5'}
__contains__ was called.
getActivityCodes() was called.
__iter__ was called.
error: Invalid("code: Value must be one of: 1; 2; 3; 4 (not '5')",
{'code': '5'}, None, None,
{'code': Invalid(u"Value must be one of: 1; 2; 3; 4 (not '5')",
'5', None, None, None)})
你有沒有看到我的回答如下?如果是這樣,是否有任何進一步的幫助或我可以提供的信息,以便您可以接受? –