Repository: web2py/web2py

Issue:
SQLFORM formstyle overridden when validation fails
A portion of SQLFORM.accepts() overrides widgets that have been explicitly set in the DAL and styled with a formstyle, when the form has failed validation.  I do not understand what the point of the for-loop that does this is, and I've commented it out in my source with no problems (so far), which fixes the styling issue.

```
    elif (not ret) and (not auch):
        # auch is true when user tries to delete a record
        # that does not pass validation, yet it should be deleted
        for fieldname in self.fields:

            field = (self.table[fieldname]
                     if fieldname in self.table.fields
                     else self.extra_fields[fieldname])
            # this is a workaround! widgets should always have default not None!
            if not field.widget and field.type.startswith('list:') and \
                    not OptionsWidget.has_options(field):
                field.widget = self.widgets.list.widget
            if field.widget and fieldname in request_vars:
                if fieldname in self.request_vars:
                    value = self.request_vars[fieldname]
                elif self.record:
                    value = self.record[fieldname]
                else:
                    value = field.default
                row_id = '%s_%s%s' % (
                    self.table, fieldname, SQLFORM.ID_ROW_SUFFIX)
                widget = field.widget(field, value)
                parent = self.field_parent[row_id]
                if parent:
                    parent.components = [widget]
                    if self.errors.get(fieldname):
                        parent._traverse(False, hideerror)
                self.custom.widget[fieldname] = widget
        self.accepted = ret
        return ret
```

In my case:
Field('string1') keeps its bootstrap styling
Field('string2', widget=SQLFORM.widgets.string.widget) loses its bootstrap styling (as does any field with widget=...)

It breaks the styling because formstyle is run during FORM.**init**(), which always occurs before FORM.accepts()



Discussion:
can we close this @timnyborg given that #1049 has been merged ?

#1049 wasn't merged, so this is awaiting a solution from @mdipierro, unless I can figure something out

This is hard to fix in current form logic. Will be addressed in new forms.

This continues to a be a problem, which makes it hard to customize widgets in forms.  Any possibility of getting it fixed?
If the point of this (see Massimo's comment on https://github.com/web2py/web2py/pull/1049) is to prevent list:string from getting wiped out, can we not change the following?

`if field.widget and fieldname in request_vars:`
to
`if field.widget == self.widgets.list.widget and fieldname in request_vars:`

This leaves all other widgets untouched, and lets the routine do its work for list:strings using ListWidget.  list:strings using other widgets (Checkboxes, Radios, standard option list) don't have this problem

Resolving patch:
diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py
--- a/gluon/sqlhtml.py
+++ b/gluon/sqlhtml.py
@@ -1814,7 +1814,7 @@ def accepts(
                 if not field.widget and field.type.startswith('list:') and \
                         not OptionsWidget.has_options(field):
                     field.widget = self.widgets.list.widget
-                if field.widget and fieldname in request_vars:
+                if field.widget == self.widgets.list.widget and fieldname in request_vars:
                     if fieldname in self.request_vars:
                         value = self.request_vars[fieldname]
                     elif self.record:


Test patch: