Bug: SQLFORM.accepts() breaks formstyle when widgets are defined

25 views
Skip to first unread message

tim.n...@conted.ox.ac.uk

unread,
Feb 19, 2015, 12:09:34 PM2/19/15
to
I'm using a custom formstyle to apply bootstrap3 to my forms (a modified copy of the built-in bootstrap3_inline).  Importantly, it adds the form-control class to each input.

This works fine, until you define a widget for a field, and have it fail validation.

db.define_table('test',
    Field('one', 'string', requires=IS_MATCH('STUFF')),
    Field('two', 'string', requires=IS_MATCH('STUFF'), widget=SQLFORM.widgets.string.widget),    
    )

def index():
    form = SQLFORM(db.test, formstyle='bootstrap3_inline')  
    form.process()
    
    return dict(form=form)

Despite being identical fields, with identical widgets, field two loses its formatting.  Why?  Because of the following code at the bottom of SQLFORM.accepts()

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


If a field's widget is defined, it overwrites it, for reasons mysterious to me.  This occurs after the formstyle is applied.

If I remove that source code, or remove the widget between form setup and validation:


def index():
    form = SQLFORM(db.test, formstyle='bootstrap3_inline')  
    db.test.two.widget=None  
    form.process()
    
    return dict(form=form)


Then everything works fine.  

What is the point of that code at the end of accepts(), and is this working as designed?
Reply all
Reply to author
Forward
0 new messages