Pylons FormEncode with an array of form elements
Question: I have a Pylons app and am using FormEncode and HtmlFill to handle my forms. I
have an array of text fields in my template (Mako)

    
    
      <tr>
        <td>Yardage</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
        <td>${h.text('yardage[]', maxlength=3, size=3)}</td>
      </tr>
    

However, I can't seem to figure out how to validate these fields. Here is the
relevant entry from my Schema

`yardage = formencode.ForEach(formencode.validators.Int())`

I'm trying to validate that each of these fields is an Int. However, no
validation occurs for these fields.

**UPDATE** As requested here is the code for the action of this controller. I
know it was working as I can validate other form fields.

    
    
        def submit(self):
            schema = CourseForm()
            try:
                c.form_result = schema.to_python(dict(request.params))
            except formencode.Invalid, error:
                c.form_result = error.value
                c.form_errors = error.error_dict or {}
                c.heading = 'Add a course'
                html = render('/derived/course/add.html')
                return htmlfill.render(
                    html,
                    defaults = c.form_result,
                    errors = c.form_errors 
                    )
            else:
                h.redirect_to(controler='course', action='view')
    

**UPDATE** It was suggested on IRC that I change the name of the elements from
`yardage[]` to `yardage` No result. They should all be ints but putting in f
into one of the elements doesn't cause it to be invalid. As I said before, I
am able to validate other form fields. Below is my entire schema.

    
    
    import formencode
    
    class CourseForm(formencode.Schema):
        allow_extra_fields = True
        filter_extra_fields = True
        name = formencode.validators.NotEmpty(messages={'empty': 'Name must not be empty'})
        par = formencode.ForEach(formencode.validators.Int())
        yardage = formencode.ForEach(formencode.validators.Int())
    


Answer: Turns out what I wanted to do wasn't quite right.

**Template** :

    
    
    <tr>
      <td>Yardage</td>
      % for hole in range(9):
      <td>${h.text('hole-%s.yardage'%(hole), maxlength=3, size=3)}</td>
      % endfor
    </tr>
    

(Should have made it in a loop to begin with.) You'll notice that the name of
the first element will become `hole-1.yardage`. I will then use
`[FormEncode.variabledecode](http://www.formencode.org/en/latest/modules/variabledecode.html)`
to turn this into a dictionary. This is done in the

**Schema** :

    
    
    import formencode
    
    class HoleSchema(formencode.Schema):
        allow_extra_fields = False
        yardage = formencode.validators.Int(not_empty=True)
        par = formencode.validators.Int(not_empty=True)
    
    class CourseForm(formencode.Schema):
        allow_extra_fields = True
        filter_extra_fields = True
        name = formencode.validators.NotEmpty(messages={'empty': 'Name must not be empty'})
        hole = formencode.ForEach(HoleSchema())
    

The HoleSchema will validate that `hole-#.par` and `hole-#.yardage` are both
ints and are not empty. `formencode.ForEach` allows me to apply `HoleSchema`
to the dictionary that I get from passing `variable_decode=True` to the
`@validate` decorator.

Here is the `submit` action from my

**Controller** :

    
    
    @validate(schema=CourseForm(), form='add', post_only=False, on_get=True, 
              auto_error_formatter=custom_formatter,
              variable_decode=True)
    def submit(self):
        # Do whatever here.
        return 'Submitted!'
    

Using the `@validate` decorator allows for a much cleaner way to validate and
fill in the forms. The `variable_decode=True` is very important or the
dictionary will not be properly created.

