【问题标题】:Validating many fields as they were one?验证多个字段,因为它们是一个字段?
【发布时间】:2012-02-29 14:19:11
【问题描述】:

我的输入格式很奇怪,但符合规范:

用户应在 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)

...

【问题讨论】:

  • FormField 不接受任何验证器。但是您可以创建一个自定义验证器,通过other = form[self.fieldname] 访问其他字段。

标签: python html forms google-app-engine wtforms


【解决方案1】:

看起来 WTForms 使用 field enclosures 解决了这个问题。该链接中的示例适用于具有单独区号和号码字段字段的电话号码,这与您的多部分 ID 号码用例非常相似。

要正确呈现子表单,您必须定义一个自定义小部件。看看the source code for ListWidget。您的小部件可能会相似但更简单(因为我认为您只需要不同字段之间的空格,而不是 HTML 标记)。像

这样简单的东西
return HTMLString(u' '.join([subfield() for subfield in field]))

可能适合您的需求。然后将widget=SingleLineWidget()(或任何您命名的小部件类)放入FormField 构造函数的参数中。

有点题外话,在 Django Forms 中执行此操作的相应方法相当不同:您定义 custom clean and validate methods 来转换您的数据(即在这种情况下,将 4 个 ID 字段合并为一个)。

【讨论】:

  • 感谢您提供此信息。我应该使用 FormField 还是 FieldList?使用 FormField 我可以创建一个示例,但无法正确渲染。我正在用新结果更新问题。再次感谢您的回答,如果可以请详细说明。
  • 我编辑了我的答案,包括使用自定义小部件的解释,让它看起来像你想要的那样。 FieldList 用于一组相同的字段...与您正在执行的操作相匹配,因此通过允许您使用数组索引引用 4 个字段,它可以使您的代码更简洁。
猜你喜欢
  • 2018-06-05
  • 2020-02-17
  • 2020-10-23
  • 2011-10-12
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
  • 2017-10-28
  • 2015-02-07
相关资源
最近更新 更多