SQLFORM with extra_fields

50 views
Skip to first unread message

Jim S

unread,
May 1, 2020, 11:53:36 AM5/1/20
to web2py-users
Anyone have experience with using 'extra_fields' in a SQLFORM?

Here is my code:


def edit_demo():
    response
.view = 'producer/edit/edit_demo.load'

    producer_id
= request.get_vars.producer_id

    producer
= db(db.producer.id == producer_id).select().first()

    form
= None
   
if producer:
        fields
= ['name', 'address', 'city',
                 
'state', 'zip_code', 'primary_contact',
                 
'primary_phone', 'primary_email', 'secondary_contact',
                 
'secondary_phone', 'secondary_email', 'grade',
                 
'district']

        extra_fields
= []
       
for pt in db(db.producer_type.id > 0).select(orderby=db.producer_type.name):
           
if db((db.producer_producer_type.producer_type == pt.id) &
                 
(db.producer_producer_type.producer == producer.id)).select().first():
                has_producer_type
= True
           
else:
                has_producer_type
= False
            extra_fields
.append(Field(fieldname='pt%s' % pt.id,
                                      type
='boolean',
                                     
default=has_producer_type,
                                      label
=pt.name))

        form
= SQLFORM(db.producer, record=producer_id, fields=fields,
                       showid
=False, extra_fields=extra_fields,
                       table_name
='edit_demographics', formname='edit_demographics_form')

       
if form.process().accepted:

            response
.flash = None

            url
= URL('index', args=['edit', 'producer', producer_id], user_signature=True, extension=False)
            url
+= '&jump=demographics_jump'
            redirect
(url, client_side=True)

   
return dict(form=form, is_owner=is_owner, is_admin=is_admin)

And it is giving me this error:

Traceback (most recent call last):
 
File "/home/jim/dev/web2py/gluon/restricted.py", line 219, in restricted
 
exec(ccode, environment)
 
File "/home/jim/dev/web2py/applications/connect/controllers/producer.py", line 1621, in <module>
 
File "/home/jim/dev/web2py/gluon/globals.py", line 422, in <lambda>
 
self._caller = lambda f: f()
 
File "/home/jim/dev/web2py/applications/connect/controllers/producer.py", line 1609, in edit_demo
 table_name
='edit_demographics', formname='edit_demographics_form')
 
File "/home/jim/dev/web2py/gluon/sqlhtml.py", line 1505, in __init__
 
default = record[fieldname]
 
File "/home/jim/dev/web2py/gluon/packages/dal/pydal/objects.py", line 145, in __getitem__
 
raise KeyError(key)
KeyError: 'pt3'

I'm not understanding how to define extra_fields in this context. In the end, the form is supposed to look like the attached. I'm trying to add the checkboxes at the bottom of the form.

I have it all working with SQLFORM.factory but would prefer that I do it with the base SQLFORM. Thoughts?


-Jim

extra_fields.jpg

Clemens

unread,
May 1, 2020, 2:16:36 PM5/1/20
to web2py-users
Hi Jim,

I've solved it as follows (for an additional field to select the corresponding business unit, here stored in a dictionary):

biz_unit = TR(TD(LABEL(T('Responsible'), XML('&nbsp&nbsp'))), \
TD(SELECT(_name='biz_unit', value='', *[OPTION(biz_unit_title, _value=biz_unit_dict[biz_unit_title]) \
for biz_unit_title in sorted(biz_unit_dict)])))
form[0].insert(-1, biz_unit)

Hope it helps!

Best regards
Clemens

Jim S

unread,
May 1, 2020, 2:38:55 PM5/1/20
to web2py-users
Clemens

Thanks for this.

Have you ever used extra_fields in SQLFORM?

I'm wondering what it is for if it doesn't work the way I'm using it.

-Jim

Jim S

unread,
May 1, 2020, 3:22:11 PM5/1/20
to web2py-users
Soooo, I'm wondering if this is a bug in web2py.  In the traceback above you can see the error is on line 1505 in sqlhtml.py.  In looking at the code, it appears as though it is just setting the default value for each field based on the record that was retrieved.

Here is that block of code:
if record:
   
default = record[fieldname]
else:
   
default = field.default
   
if isinstance(default, CALLABLETYPES):
       
default = default()

With extra_fields we don't want to set the default from the database because these fields don't exist in the database.  We want to set it based upon the field definition.  So, to me, the right fix is:

if record and fieldname not in [x.name for x in extra_fields]:
   
default = record[fieldname]
else:
   
default = field.default
   
if isinstance(default, CALLABLETYPES):
       
default = default()

With this change to the if statement it only sets the default from the retrieved record if the field is not in extra_fields.

I've tested with my app and it works well.

I'll try submitting a PR to get it added to the codebase.

-Jim
Reply all
Reply to author
Forward
0 new messages