How to get a build a form with repeated elements well

前端 未结 1 2013
渐次进展
渐次进展 2021-01-12 15:54

The title really doesn\'t say it, as i\'m having trouble summarizing the issue. So here goes the long explanation:

Let\'s say I\'m adding multiple contacts\' informa

1条回答
  •  清酒与你
    2021-01-12 16:25

    No need to build anything (at least on the server side) - WTForms already supports what you need - it calls them "field enclosures". The behavior you are looking for is found in wtforms.fields.FormField and wtforms.fields.FieldList

    class ContactForm(Form):
        name = TextField("Name", validators=[Required()])
        contact_type = SelectField("Contact Type",
                                    validators=[Required()],
                                    choices=[
                                        ("email", "Email"),
                                        ("phone", "Phone Number"),
                                        ("im", "Instant Message")
                                    ])
        # `If` is a custom validator - see below
        email_address = TextField("Email",
                                      validators=[If("contact_type",
                                                         "email",
                                                         [Required(), Email()])
                                      ])
        phone_number = TextField("Phone #",
                                      validators=[If("contact_type",
                                                               "phone", [Required()])
                                      ])
        im_handle = TextField("IM Handle",
                                      validators=[If("contact_type",
                                                               "im", [Required()])
                                      ])
    
    
    class SignUpForm(Form):
        # Other fields go here
        contacts = FieldList(FormField(ContactForm))
    

    You'll also need a custom validator to validate the appropriate field, given the user's choice:

    # CAUTION: Untested code ahead
    class If(object):
        def __init__(self,
                          parent,
                          run_validation=None,
                          extra_validators=None,
                          msg=None):
            self.parent = parent
            self.msg = msg if msg is not None else u"Invalid"
            if callable(run_validation):
                self.run_validation = run_validation
            else:
                _run_validation = lambda self, parent, form: parent.data == run_validation
                self.run_validation = _run_validation
            self.extra_validators = extra_validators if extra_validators is not None \
                                                         else []
    
        def __call__(self, field, form):
            parent = getattr(form, self.parent)
            if self.run_validation(parent, form):
                return field.validate(form, extra_validators=self.extra_validators)
    

    When you call form.validate() on the server side the fields will be automatically checked against the requirements and the errors will be populated appropriately so you can render them back on the client side.

    Creating new fields on the client side is simple and WTForms will pick them up on the back end as long as you name then using the same naming convention it uses - namely field.short_name + '-' + index.

    0 讨论(0)
提交回复
热议问题