wtforms表单类子类化和字段排序

2024-04-26 22:24:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个UserForm类:

class UserForm(Form):
    first_name = TextField(u'First name', [validators.Required()])
    last_name = TextField(u'Last name', [validators.Required()])
    middle_name = TextField(u'Middle name', [validators.Required()])
    username = TextField(u'Username', [validators.Required()])
    password = TextField(u'Password', [validators.Required()], widget=PasswordInput())
    email = TextField(u'Email', [validators.Optional(), validators.Email()])

并希望在UpdateUserForm中使password字段成为可选字段:

class UpdateUserForm(UserForm):
    password = TextField(u'Password', [validators.Optional()], widget=PasswordInput())

但密码字段放在电子邮件字段之后,而不是之前。

子类化时如何保持字段顺序?

另外,当我尝试更改密码字段验证器时,它不起作用-仍然需要密码:/为什么?

class UpdateUserForm(UserForm):
    def __init__(self, **kwargs):
        self.password.validators = [validators.Optional()]
        super(UpdateUserForm, self).__init__(**kwargs)

或者

class UpdateUserForm(UserForm):
    def __init__(self, **kwargs):
        self.password = TextField(u'Password', [validators.Optional()], widget=PasswordInput())
        super(UpdateUserForm, self).__init__(**kwargs)

一些想法…

class UpdateUserForm(UserForm):
    def __init__(self, formdata=None, obj=None, prefix='', **kwargs):
        self._unbound_fields[4][1] = TextField(u'Password', [validators.Optional()], widget=PasswordInput())
        UserForm.__init__(self, formdata=None, obj=None, prefix='', **kwargs)

最后,我需要:

class UpdateUserForm(UserForm):
    def __init__(self, formdata=None, obj=None, prefix='', **kwargs):
        UserForm.__init__(self, formdata, obj, prefix, **kwargs)
        self['password'].validators = [validators.Optional()]
        self['password'].flags.required = False

Tags: nameselfnoneinitrequiredpasswordwidgetoptional
3条回答

关于迭代表单对象时重新排列字段的第一个问题,我做了以下工作:

class BaseForm(Form):
    def __iter__(self):
        field_order = getattr(self, 'field_order', None)
        if field_order:
            temp_fields = []
            for name in field_order:
                if name == '*':
                    temp_fields.extend([f for f in self._unbound_fields if f[0] not in field_order])
                else:
                    temp_fields.append([f for f in self._unbound_fields if f[0] == name][0])
            self._unbound_fields = temp_fields
        return super(BaseForm, self).__iter__()

class BaseUserForm(BaseForm):
    password = PasswordField('Password', [Required()])
    full_name = TextField('Full name', [Required()])

class NewUserForm(BaseUserForm):
    username = Textfield('Username', [Required()])
    field_order = ('username', '*')

这样,当您呈现NewUserForm(可能来自一个在表单呈现字段上逐字段迭代的模板)时,您将看到usernamepasswordfull_name。通常你最后会看到username

我就是这样完成你想做的:

class UserForm(wtforms.Form):                                                   
    def __init__(self, *args, **kwargs):                                        
        super(UserForm,self).__init__(*args, **kwargs)                          

        if kwargs.get('update', None):                                          
            self['passwd'].validators.append(wtforms.validators.Optional())
            self['passwd'].flags.required = False     
        else:                                                                   
            self['passwd'].validators.append(wtforms.validators.Required()) 

    passwd = UnicodeField(                                                      
        u'Password',                                                            
        [                                                                       
            wtforms.validators.length(max=50),                                  
            wtforms.validators.EqualTo(                                         
                'confirm',                                                      
                message='Passwords must match'                                  
                )                                                               
            ],                                                                  
        widget = wtforms.widgets.PasswordInput()                                
        )                                                                       

    confirm = wtforms.PasswordField(u'Password Verify')

然后,当我实例化UserForm时,在编辑时传递update=True。这似乎对我有用。

我通过在我的Form类上定义一个附加的__order属性,并重写__iter__方法来解决这个问题,这样返回的迭代器的数据首先根据定义进行排序。它可能效率不高,但表单上没有那么多字段,可能会导致任何问题。它还可以处理子类表单中的字段。

class MyForm(Form):
    field3 = TextField()
    field1 = TextField()
    field2 = TextField()

    __order = ('field1', 'field2', 'field3')

    def __iter__(self):
        fields = list(super(MyForm, self).__iter__())
        get_field = lambda field_id: next((fld for fld in fields
                                           if fld.id == field_id))
        return (get_field(field_id) for field_id in self.__order)

相关问题 更多 >