Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

wtforms Form class subclassing and field ordering

I have a UserForm class:

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()])

and want to make the password field Optional in UpdateUserForm:

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

But the password field is placed after the email field, not before.

How do I preserve field order when subclassing?

Additionally, when I try to change the password field validators it doesn't work - password still Required :/ Why?

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

or

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

Some thoughts...

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)

Finally, what I need:

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
like image 707
sector119 Avatar asked May 01 '11 12:05

sector119


People also ask

What is Stringfield?

String field theory (SFT) is a formalism in string theory in which the dynamics of relativistic strings is reformulated in the language of quantum field theory.

What does WTForms stand for?

WTForms is a flexible forms validation and rendering library for Python web development. It can work with whatever web framework and template engine you choose. It supports data validation, CSRF protection, internationalization (I18N), and more.

What is form Validate_on_submit?

validate_on_submit() is a shortcut for is_submitted() and validate() . From the source code, line 89, is_submitted() returns True if the form submitted is an active request and the method is POST, PUT, PATCH, or DELETE.


1 Answers

In regards to your first question about reording the fields when iterating over the form object, this is what I did:

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', '*')

That way, when you render NewUserForm (perhaps from a template which iterates over the form rendering field by field), you'll see username, password, full_name. Normally you'd see username last.

like image 146
rhyek Avatar answered Nov 15 '22 20:11

rhyek