Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 5 and Version 6 of FormValidationWithWidgets


Ignore:
Timestamp:
01/31/07 10:56:49 (12 years ago)
Author:
jorge.vargas
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • FormValidationWithWidgets

    v5 v6  
    1 == Form Validation With Widgets ==  
    2 Widgets are great and widgets are fine, but there are still some API-ish 
    3 issues that haunt my sleep at nights.  Here is how I overcame my 
    4 fear and grew to love (or maybe loathe) some of the finer points of 
    5 widget wrangling. 
    6  
    7 The simple form that I was coding up was a search form.  It would have 
    8 four fields, two text entry, and two select fields.  There was a 
    9 requirement that at least two of the fields have valid entry data 
    10 associated with them. 
    11  
    12 I could have done all of this logic in the controller, but I didn't, 
    13 because it didn't smell right. 
    14  
    15 If anyone devises a finer solution to this problem, please update this 
    16 page in the way you see fit. 
    17  
    18 Here is the code to make the form work.  It should be valid unless 
    19 someone dramatically changes the widget code.  I wrote it with SVN 485. 
    20  
    21 Things of note: 
    22  
    23  * It's near impossible (or at least very difficult) to extend a 
    24    template in an existing widget.  I've tried several things, and in 
    25    the end the easiest thing to do was just copy the existing template 
    26    from the parent widget. 
    27  * It'd sure be nice if something like this, or formencode.Schema 
    28    support was attached to forms. 
    29  * Don't eat soap. 
    30  
    311{{{ 
    32 #!python 
    33 import turbogears.widgets as w 
    34 import turbogears.validators as v 
    35 import cherrypy 
    36  
    37 # these are just all of the option lists in a separate module, because 
    38 # I don't like them dirtying up the other ones. 
    39 from myapp.forms.option_select_lists import states,units 
    40  
    41 _first_name_field = w.TextField("firstName", labeltext="First Name") 
    42 _last_name_field = w.TextField("lastName", labeltext="Last Name") 
    43 _location_field = w.SelectField("state", states, labeltext="Location") 
    44 _unit_field = w.SelectField("unit", units, labeltext="Unit") 
    45  
    46 class RequireNFields(v.FancyValidator): 
    47     num_fields = 2 
    48  
    49     messages = { 
    50         'notEnough': "Please submit at least %(num_fields)s fields" 
    51         } 
    52  
    53     def validate_python(self, values, state): 
    54         num_fields_submitted = len([val for val in values.values() if val != '']) 
    55         if self.num_fields > num_fields_submitted: 
    56             raise v.Invalid(self.message('notEnough', state, num_fields=self.num_fields), values, state) 
    57  
    58 class ValidatingForm(w.Form): 
    59     def create_dict(self, *args, **kwargs): 
    60         dict = w.Form.create_dict(self, *args, **kwargs) 
    61         if not 'name' in dict: 
    62             dict['name'] = self.name 
    63         return dict 
    64          
    65     def input(self, values): 
    66         # validate the items and then validate the whole shebang 
    67         w.Form.input(self,values) 
    68         if self.validator: 
    69             try: 
    70                 self.validator.to_python(values) 
    71             except v.Invalid, error: 
    72                 cherrypy.request.form_errors[self.name] = error 
    73  
    74  
    75 # hmm need to hack the template here... 
    76 # this would be a lot easier if I could figure out how to get the  
    77 # kid template, take it apart, and jam what I want in there 
    78 class ValidatingTableForm(ValidatingForm, w.TableForm): 
    79     template = """ 
    80 <form xmlns:py="http://purl.org/kid/ns#" name="${widget.name}"  
    81       action="${getattr(self, 'action', None)}" method="${getattr(self, 'method', 'post')}" 
    82       enctype="${getattr(self, 'enctype', None)}"> 
    83     <div py:for="widget in widgets" py:if="widget.hidden" py:strip="True"> 
    84        ${widget.insert(getattr(self.widget_value, widget.name, None), input_values, widget_error.get(widget.name, None))} 
    85     </div> 
    86     <table border="0"> 
    87     <tr py:if="widget_error"> 
    88         <td> 
    89             <span class="field_error">${str(widget_error[name])}</span> 
    90         </td> 
    91     </tr> 
    92     <tr py:for="widget in widgets" py:if="not widget.hidden"> 
    93             <td> 
    94                 <span py:if="widget.label and widget.labeltext"  
    95                       py:replace="widget.label.insert(widget.labeltext)"/> 
    96                 <span py:if="not widget.label or not widget.labeltext" py:strip="True">&#160;</span> 
    97             </td> 
    98             <td>${widget.insert(getattr(self.widget_value, widget.name, None), input_values, widget_error.get(widget.name, None))}</td> 
    99         </tr> 
    100          <tr> 
    101             <td>&#160;</td> 
    102             <td>${submit.insert(submittext)}</td> 
    103         </tr> 
    104     </table> 
    105 </form> 
    106 """ 
    107  
    108  
    109 search_form = ValidatingTableForm(widgets= \ 
    110         [_first_name_field, _last_name_field,  
    111          _location_field, _unit_field], 
    112         validator=RequireNFields(), 
    113         name="searchform") 
     2#!NewsFlash 
     3This wiki page has been migrated to the new docs site currently at  
     4http://docs.turbogears.org/1.0/RoughDocs/FormValidationWithSchemas 
    1145}}}