Pylons FormEncode with an array of form elements

I have a Pylons application and I use FormEncode and HtmlFill to process 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 cannot figure out how to check these fields. Here is the corresponding entry from my schema

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

I am trying to verify that each of these fields is an Int. However, no checks are performed for these fields.

UPDATE As requested here is the action code for this controller. I know that it works, since I can check 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 The IRC suggested changing the name of the elements from yardage[] to yardage to no yardage . All of them must be ints, but the inclusion of f in one of the elements does not lead to its invalidity. As I said, I can check other form fields. Below is my whole diagram.

  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 ())
+2
source share
2 answers

It turns out that I wanted to do was not 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 done this in a loop to start.) You will notice that the name of the first element becomes hole-1.yardage . Then I use FormEncode.variabledecode to turn this into a dictionary. This is done in

Scheme

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

HoleSchema will verify that hole-#.par and hole-#.yardage are both int and 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 you to use a cleaner way to validate and fill out forms. variable_decode=True very important or the dictionary will not be created correctly.

+5
source
 c.form_result = schema.to_python(request.params) - (without dict) 

Everything seems to be fine.

+1
source

All Articles