Actually, I borrowed Anthony's excellent idea and made a "factory" class 
for my field definitions.

First I defined a factory class:

class Field_Factory(object):
    from gluon import Field
    def new(**kwargs):
        default = dict(**kwargs)
        def inner(name, **kwargs):
            args = dict(default)
            if args.pop('hidden',False):
            req = args.get('requires', None)
            if req and (args.get('represent',None)=='formatter'):
                args['represent'] = req.formatter
            if args.pop('optional',False) and req:
                args['requires'] = IS_EMPTY_OR(req)
            rend = args.pop('render',None)
            rtn = Field(name, **args)
            if rend:
                rtn.render = rend
            return rtn
        return inner

factory = Field_Factory()

Then I used it to create a bunch of field generators:

phone_field =
    type='string', length=20,
    requires=IS_PHONE(), optional=True,
    widget=lambda fld,val: SQLFORM.widgets.string.widget(
        fld, val, _type='tel', _class='form-control')

email_field =
    type='string', length=50,
    requires=IS_EMAIL(), optional=True,
    widget=lambda fld,val: SQLFORM.widgets.string.widget(
        fld, val, _type='email', _class='form-control')

date_field =
    requires=IS_DATE(format='%m-%d-%Y'), optional=True,
    represent=lambda v,r: v.strftime('%m-%d-%Y'),
    widget=lambda fld,
        fld, val, _class="date form-control")

datetime_field =
    requires=IS_DATETIME(format='%m-%d-%Y %I:%M:%S %p'), optional=True,
    represent=lambda v,r: v.strftime('%m-%d-%Y %I:%M:%S %p'),
    widget=lambda fld,val: SQLFORM.widgets.datetime.widget(
        fld, val, _class="datetime form-control")

zipcode_field =
    type='string', length=10,
    widget=lambda fld,val: SQLFORM.widgets.string.widget(
        fld, val, _type="zip", _class='zipcode form-control')

Finally, when I use the field generators in any table definitions, I can 
further customize them and the changes are passed through.  

    . . .
    date_field("birth", label=T("Birth date")),
    . . .

It all works really well and gives me the single point of control I want. 
 It requires no changes in web2py and works with current, past, and future 
versions.  And the lazy programmer in me marvels at all the code I don't 
have to type.

-- Joe

On Thursday, March 23, 2017 at 12:54:58 PM UTC-7, Joe Barnhart wrote:
> Here is a bit of syntactic sugar I use for creating fields with less 
> typing.  And better consistency, of course -- there always has to be a good 
> reason for my lazy keyboard-saving shortcuts!
> I have a number of fields which are for specific data types, such as phone 
> numbers.  I gather the "common" parts of the Field definition into a 
> dictionary:
> phone_fld = {'requires':IS_EMPTY_OR(IS_PHONE()),
>              'widget':lambda fld,val: SQLFORM.widgets.string.widget(fld,
> val,_type='tel',_class='form-control')}
> When defining the field in a table, I invoke the dictionary at the end of 
> the Field definition:
> Field("homephone","string",length=20,label=T("Home phone"),**phone_fld),
> Field("workphone","string",length=20,label=T("Work phone"),**phone_fld),
> Field("cellphone","string",length=20,label=T("Cell phone"),**phone_fld),
> Now the field is created exactly as I want.  I keep a list of these 
> "helpers" in a module which I can call out when creating tables.  It really 
> saves the typing and allow me to control how my fields are rendered on one 
> place instead of scattered among all the tables.
> -- Joe

- (Documentation)
- (Source code)
- (Report Issues)
You received this message because you are subscribed to the Google Groups 
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
For more options, visit

Reply via email to