我正在尝试验证模型中的值,并获得经过验证的值作为输出。文档中唯一的示例是以下代码,该代码未显示此操作的执行方式,因此我无法对其进行扩展。
>>> from schematics.models import Model
>>> from schematics.types import StringType, BooleanType
>>> from schematics.exceptions import ValidationError
>>>
>>> class Signup(Model):
... name = StringType()
... call_me = BooleanType(default=False)
... def validate_call_me(self, data, value):
... if data['name'] == u'Brad' and data['call_me'] is True:
... raise ValidationError(u'He prefers email.')
... return value
...
>>> Signup({'name': u'Brad'}).validate()
>>> Signup({'name': u'Brad', 'call_me': True}).validate()
Traceback (most recent call last):
...
ModelValidationError: {'call_me': [u'He prefers email.']}
我制作了一个版本,但从参数中删除了data
和value
。 Client
是我的模型的名称。因此,当我执行以下操作时,将得到期望的结果作为输出:
client.validate_client(client.to_native())
但是,
首先,这似乎不是一种干净的方法。 client
已经具有所有值,因此我不需要这样做。
此外,我喜欢获取它来更新客户端的值,作为验证的结果。
对于第一部分,我做了以下内容:
def validate_client(self):
data = self.to_native()
...
return data
但是我不认为这是执行此操作的最佳方法,并且我不确定第二个更新值的问题。有办法吗?
编辑:
这是我拥有的代码,我希望将雇主的客户值设置为'unspecified'
,并将客户full_name
设置为函数中指定的值。
class LowerCaseEmailType(EmailType):
def convert(self, value, context=None):
value = super(LowerCaseEmailType, self).convert(value, context)
return value.lower()
class CleanedStringType(StringType):
converters = []
def __init__(self, **kwargs):
"""
This takes in all the inputs as String Type, but takes in an extra
input called converters.
Converters must be a list of functions, and each of those functions
must take in exactly 1 value , and return the transformed input
"""
if 'converters' in kwargs:
self.converters = kwargs['converters']
del kwargs['converters']
super(CleanedStringType, self).__init__(**kwargs)
def convert(self, value, context=None):
value = super(CleanedStringType, self).convert(value, context)
for func in self.converters:
value = func(value)
return value # will have a value after going through all the conversions in order
class Client(Model):
"""
Client Model
"""
first_name = CleanedStringType(required=False,
converters=[lambda x: re.sub(r"[!@#$%&\(\)\^]+", ' ', x),
lambda x: x.strip()])
last_name = CleanedStringType(required=False,
converters=[lambda x: re.sub(r"[!@#$%&\(\)\^]+", ' ', x),
lambda x: x.strip()])
full_name = CleanedStringType(required=False,
converters=[lambda x: re.sub(r"[!@#$%&\(\)\^]+", ' ', x),
lambda x: x.strip()])
employer = StringType(required=False)
created = StringType(default=" ")
updated = StringType(default=" ")
email = LowerCaseEmailType(required=False)
def validate_client(self):
data = self.to_native()
if data.get('first_name') and data.get('last_name'):
data['full_name'] = ' '.join([data['first_name'], data['last_name']])
if data.get('full_name') is None:
if data.get('first_name') is None:
error_message = 'first name missing'
else:
error_message = 'last name missing'
logger.error('info: {} for {}'.format(error_message, data))
raise ValidationError(error_message)
if data.get('employer') is None:
logger.warning('info: employer missing for {}'.format(data))
data['employer'] = 'unspecified'
return data
答案 0 :(得分:0)
我认为您想要pre_setattr
。当您设置模型的值(有问题的code时,该值会被调用。
对于雇主,我想您要设置默认值。对我来说,这似乎完全符合您的要求。
我认为fullname
不应放在模型上,因为firstname + lastname != fullname
处的数据可能不一致。如果以后需要,可以通过@serialized
来实现。