如何在WTForms中有条件地选择字段? [英] How to make a field conditionally optional in WTForms?

查看:208
本文介绍了如何在WTForms中有条件地选择字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的表单验证工作接近完成,我只有2个案例,我不知道如何解决:1)密码字段应该是必需的,但我也提供了使用谷歌或Facebook帐户登录的可能性通过OAuth,然后名称预填充,但我完全从表单中删除密码字段是有一个用户(谷歌)或Facebook用户对象:

 < TR>< TD> 
< br /> {%if user or current_user%} {%else%}

< div class =labelform>
{%filter capitalize%} {%trans%}密码{%endtrans%} {%endfilter%}:
< / div>
< / td>< td> < div class =adinput> {{form.password | safe}} {%trans%}选择密码{%endtrans%}< / div> {%endif%}

< / TD>< / TR>

因此,对于已经登录并且密码字段没有任何意义的用户,我需要一些逻辑使该字段有条件可选。我在想,我可以为我的表单类中的logged_in +方法添加一个变量,如下所示:

  class AdForm(Form ):
logged_in = False
my_choices = [('1',_('VEHICLES')),('2',_('Cars')),('3',_('自行车'))]
name = TextField(_('Name'),[validators.Required(message = _('Name is required'))],widget = MyTextInput())
title = TextField(_('title'),[validators.Required(message = _('Subject is required'))],widget = MyTextInput())
text = TextAreaField(_('Text'),[validators (_('Display'))。(必须的)(message = _('Text is required'))],widget = MyTextArea())
phonenumber = TextField(_('Phone number'))
phoneview =电话号码'))
price = TextField(_('Price'),[validators.Regexp('\d',message = _('这不是一个整数,请看例子和再试')),validators.Optional()])
password = PasswordFie ld(_('Password'),[validators.Optional()],widget = PasswordInput())
email = TextField(_('Email'),[validators.Required(message = _('Email is ')),validators.Email(message = _('Your email is invalid'))],widget = MyTextInput())
category = SelectField(choices = my_choices,default ='1')

def validate_name(form,field):
if len(field.data)> 50:
raise ValidationError(_('Name must be less than 50 characters'))

def validate_email(form,field):
if len(field.data)> ; 60:
raise ValidationError(_('Email must be 60 characters'))

def validate_price(form,field):
if len(field.data)> ; 8:
raise ValidationError(_('价格必须小于9整数'))

def validate_password(表单,字段):
如果不是logged_in而不是字段:
raise ValidationError(_('Password is required'))

以上validate_password是否工作达到预期的效果?还有更好的方法吗?我可以考虑的另一种方法是有两种不同的表单类,在http post中,我应该使用表单类: post(self):
如果不是current_user:
form = AdForm(self.request.params)
如果current_user:
form = AdUserForm(self.request.params)

我还需要对类别字段进行条件验证,当某个类别被选中时,会出现更多的选项,仅对某个基本类别进行验证,例如。用户选择汽车,然后通过Ajax可以选择汽车的注册数据和里程数,并且这些字段是必需的,因为选择了汽车类别。所以它可能是两个问题,但这两种情况都与我如何使字段有条件地可选或有条件需要有关。

我的表单看起来像这样





对于已登录的用户,我预先填写名称和电子邮件地址,并且密码字段不被使用,所以密码字段既不适用于可选也不适用需要,它需要类似有条件地可选或有条件地要求。





感谢您的任何回答或评论

解决方案

我不是确定这很符合你的需求,但我已经使用了 Re quiredIf 之前的字段上的自定义验证器,如果另一个字段具有值形式...,例如,在日期时间和时区方案中,我可以使时区字段为必填字段如果用户输入了日期时间,就有一个值。

  class RequiredIf(必需):
验证器如果
#另一个字段被设置并且具有真值,

def __init __(self,other_field_name,* args,** kwargs):
self.other_field_name = other_field_name
super(RequiredIf,self).__ init __(* args,** kwargs)
$ b $ def __call __(self,form,field):
other_field = form._fields.get (self.other_field_name)
如果other_field是None:
抛出异常('没有名字为'%s'的字段'self.other_field_name')
if bool(other_field.data):
super(RequiredIf,self).__ call __(form,field)

T他的构造函数需要触发其他字段的名称,例如:

$ p $ 类DateTimeForm(Form):
datetime = TextField()
timezone = SelectField(choices = ...,validators = [RequiredIf('datetime')])

这可能是实现您所需逻辑的一个很好的起点。


My form validation is working nearly complete, I just have 2 cases I don't know exactly how to solve: 1) The password field should be required of course but I also provide the possibility to log in with google or facebook account via OAuth and then name gets prefilled but I remove the password field completely from the form is there is a user (google) or a facebook user object:

<tr><td>
  <br />        {% if user or current_user %}    {% else %} 

  <div class="labelform">
     {% filter capitalize %}{% trans %}password{% endtrans %}{% endfilter %}:
  </div>
      </td><td>  <div class="adinput">{{ form.password|safe }}{% trans %}Choose a password{% endtrans %}</div>{% endif %}

  </td></tr>

So for these users who already are logged in and the password field has no meaning, I need some logic to make that field conditionally optional. I was thinking that I could have a variable for logged_in + a method in my form class such as this:

class AdForm(Form):
    logged_in = False
    my_choices = [('1', _('VEHICLES')), ('2', _('Cars')), ('3', _('Bicycles'))]
    name = TextField(_('Name'), [validators.Required(message=_('Name is required'))], widget=MyTextInput())
    title = TextField(_('title'), [validators.Required(message=_('Subject is required'))], widget=MyTextInput())
    text = TextAreaField(_('Text'),[validators.Required(message=_('Text is required'))], widget=MyTextArea())
    phonenumber = TextField(_('Phone number'))
    phoneview = BooleanField(_('Display phone number on site'))
    price = TextField(_('Price'),[validators.Regexp('\d', message=_('This is not an integer number, please see the example and try again')),validators.Optional()] )
    password = PasswordField(_('Password'),[validators.Optional()], widget=PasswordInput())
    email = TextField(_('Email'), [validators.Required(message=_('Email is required')), validators.Email(message=_('Your email is invalid'))], widget=MyTextInput())
    category = SelectField(choices = my_choices, default = '1')

    def validate_name(form, field):
        if len(field.data) > 50:
            raise ValidationError(_('Name must be less than 50 characters'))

    def validate_email(form, field):
        if len(field.data) > 60:
            raise ValidationError(_('Email must be less than 60 characters'))

    def validate_price(form, field):
        if len(field.data) > 8:
            raise ValidationError(_('Price must be less than 9 integers'))

    def validate_password(form, field):
        if not logged_in and not field:
            raise ValidationError(_('Password is required'))

Will the above validate_password work to achieve the desired effect? Is there another better way? Another way I could think is to have 2 different form class and in http post I instanciate the form class it should be:

def post(self):
    if not current_user:
      form = AdForm(self.request.params)
    if current_user:
      form = AdUserForm(self.request.params)

I also need conditional validation for the category field, when a certain category is selected then more choices appear and these should have validation only for a certain base-category eg. user selects "Car" and then via Ajax can choose registration data and mileage for the car and these fields are required given that the category Car was selected.

So it might be two questions but both cases relate to how I can make a field "conditionally optional" or "conditionally required".

My form looks like this

And for a logged in user I prefill the name and email address and the pasword field is simply not used, so the password field neither fits being "optional" nor "required", it would need something like "conditionally optional" or "conditionally required."

Thanks for any answer or comment

解决方案

I'm not sure this quite fits your needs, but I've used a RequiredIf custom validator on fields before, which makes a field required if another field has a value in the form... for instance, in a datetime-and-timezone scenario, I can make the timezone field required to have a value if the user has entered a datetime.

class RequiredIf(Required):
    # a validator which makes a field required if
    # another field is set and has a truthy value

    def __init__(self, other_field_name, *args, **kwargs):
        self.other_field_name = other_field_name
        super(RequiredIf, self).__init__(*args, **kwargs)

    def __call__(self, form, field):
        other_field = form._fields.get(self.other_field_name)
        if other_field is None:
            raise Exception('no field named "%s" in form' % self.other_field_name)
        if bool(other_field.data):
            super(RequiredIf, self).__call__(form, field)

The constructor takes the name of the other field that triggers making this field required, like:

class DateTimeForm(Form):
    datetime = TextField()
    timezone = SelectField(choices=..., validators=[RequiredIf('datetime')])

This could be a good starting point for implementing the sort of logic you need.

这篇关于如何在WTForms中有条件地选择字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆