durusmail: qp: Form.is_submitted() and Widget.parse()
Form.is_submitted() and Widget.parse()
2006-05-25
2006-05-25
2006-06-01
Form.is_submitted() and Widget.parse()
mario ruggier
2006-05-25
Hi,

this is an old itch that keeps coming back when working with quixote/qp
forms. The issue is 2-fold:
- Form.is_submitted(), when the form's method is GET, does not care to
check which form we are concerned about.
- If we render() the form, each widget's render() is called in turn,
that then calls Widget.parse(). This method implements its own
"meaning" of "is submitted", that is different than that of a Form.

The current code:

Form:

     def is_submitted(self):
         """() -> bool

         Return true if a form was submitted.  If the form method is
'POST'
         and the page was not requested using 'POST', then the form is
not
         considered to be submitted.  If the form method is 'GET' then
the
         form is considered submitted if there is any form data in the
         request.
         """
         if self.method == 'post':
             return get_request().get_method() == 'POST'
         else:
             return bool(get_request().get_fields())

Widget:

     def parse(self, request=None):
         if not self._parsed:
             self._parsed = True
             if request is None:
                 request = get_request()
             if request.get_fields() or request.get_method() == 'POST':
#<<
                 try:
                     self._parse(request)
                 except WidgetValueError, exc:
                     self.set_error(stringify(exc))
                 if (self.required and self.value is None and
                     not self.has_error()):
                     self.set_error('required')
         return self.value

The "is submitted" check in parse() (#<<) is problematic because if a
specific form is NOT submitted, but there happens to be some query
string parameters in the URL requested doing a GET (even if the form's
method is POST), e.g. from URL-hacking garbage, then the widget will be
rendered with its error, if any...

I feel that the if "is submitted" check in parse() should behave in
exactly the same way as Form.is_submitted(). It should probably execute
the same code... or at least use the same cached result....

The other issue, about being a little more specific about which form
instance we are talking about when we call Form.is_submitted() and the
method is GET, why would we not check for only incoming field names
that are actually widgets of this form? Something like:

     def is_submitted(self):
         request = get_request()
         if self.method == 'post':
             return request.get_method() == 'POST'
         else:
             for name in self._names:
                 if bool(request.get_field(name)):
                     return True
             return False


m.

reply