将多个字段作为一个进行验证?
我的输入格式有点奇怪,但按照规范来讲是这样的:
用户需要在4个字段中输入一个ID,这个ID的格式是460 000 005 001,其中46是国家代码,后面的部分是用户的appengine ID。现在我想给这个字段添加验证,但我在使用wtforms时遇到了问题。以下是我的表单类:
class RegisterWTForm(Form):
soc_sec = TextField(_('Soc security number'), [validators.Regexp('^[0-9]+$',
message=_('This is not a social security number, please see the example and try again'
)), validators.Required(message=_('Social security number is required')), unique_soc_sec], widget=MyTextInput())
email = TextField(_('Email'),
[validators.Required(message=_('Email is required'
)),
validators.Email(message=_('Your email is invalid'
))], widget=MyTextInput())
def validate_soc_sec(form, field):
if len(field.data) != 10:
raise ValidationError(_('Soc sec must be 10 characters'
))
def validate_email(form, field):
if len(field.data) > 60:
raise ValidationError(_('Email must be less than 60 characters'
))
现在我使用这些变量的方式是,它们并不是WTForm的一部分,而是普通的http post参数:
def post(self):
Log1 = self.request.POST.get('Log1')
Log2 = self.request.POST.get('Log2')
Log3 = self.request.POST.get('Log3')
Log4 = self.request.POST.get('Log4')
form = RegisterWTForm(self.request.params)
if form.validate():
logging.info('validated successfully')
else:
logging.info('form did not validate')
self.render_jinja('register.html', form=form, Log1=Log1, Log2=Log2, Log3=Log3, Log4=Log4 )
return ''
email = self.request.POST.get('email')
sponsor_id = '%s%s%s' % (Log2, Log3, Log4)
if sponsor_id:
user = User.get_by_id(long(sponsor_id))
else:
return 'Sponsor with sponsor id %s does not exist' % sponsor_id
if not user:
return 'Sponsor with sponsor id %s does not exist' % sponsor_id
# make a token for a one-time login link that sets the password
# Passing password_raw=password so password will be hashed
# Returns a tuple, where first value is BOOL. If True ok, If False no new user is created
user = self.auth.store.user_model.create_user(email)
有没有办法把我的4个变量作为一个变量添加到WTForm中,并在里面进行验证?还是说我应该为这些字段自己写一个自定义的验证?对于我的其他字段,如果验证不通过,我会用红色边框和红色文字来标记,我也想在这里做到这一点,但如果不能在表单类中处理,就得把逻辑放到模板里,这样会让展示层的逻辑变得复杂。你能给我一些建议吗?
谢谢
更新
我可以创建一个FormField来组合这些字段,但它们的显示效果不太对,而且我并不需要所有4个字段的验证。也许你能告诉我更多如何按照我想要的方式来做?
class SponsorWTForm(Form):
log1 = IntegerField('log1', [validators.required()])
log2 = IntegerField('log2', [validators.required()])
log3 = IntegerField('log3', [validators.required()])
log4 = IntegerField('log4', [validators.required()])
class RegisterWTForm(Form):
sponsor_id = FormField(SponsorWTForm)
...
1 个回答
看起来WTForms是通过字段封装来解决这个问题的。链接中的例子是关于一个电话号码的,它把区号和号码分开,这跟你提到的多部分身份证号的情况很相似。
要正确显示这个子表单,你需要定义一个自定义的小部件。可以看看ListWidget的源代码。你的这个小部件可能会类似,但会更简单(因为我觉得你只需要在不同的字段之间留个空格,而不是HTML标签)。像这样简单的代码
return HTMLString(u' '.join([subfield() for subfield in field]))
可能就能满足你的需求。然后在FormField
构造函数的参数中加上widget=SingleLineWidget()
(或者你给你的小部件类起的其他名字)。
稍微偏题一点,在Django表单中实现这个功能的方法就很不一样了:你需要定义自定义的清理和验证方法,这些方法会处理你的数据(比如在这个例子中,把4个身份证字段合并成一个)。