A table definition from the DAL chapter of the Web2py book: db.define_table('person', Field('uuid', length=64, default=uuid.uuid4()), Field('modified_on', 'datetime', default=now), Field('name'), format='%(name)s')
"now" usually contains the current datetime from request.now and that's fine but the default for "uuid" would be identical for all inserts. Although the example doesn't use the default so it is not a problem there. If you omit the parenthesis behind "default=uuid.uuid4()" and simple pass the uuid4 function as the default it works as expected - the default is evaluated at insert time and yields a fresh uuid for each new record. I assume this is the intended behaviour although I couldn't find it documented(!?). Strangely replacing "default=now" in the same way with e.g. "default=datetime.datetime.now" does not work: now=datetime.datetime.now db.define_table('person', Field('uuid', length=64, default=uuid.uuid4), Field('modified_on', 'datetime', default=now), Field('name'), format='%(name)s') db.person.insert(name='Ernie') db.person.insert(name='Bert') db(db.person).select() >>> ValueError: invalid literal for int() with base 10: '<built' Umm,... db.executesql(db(db.person)._select()) >>> [(1, u'b35cc052-3800-42a9-b7eb-bb9bc8ada271', u'<built-in method now of type object at 0x37c520>', u'Ernie'), (2, u'003ab438-f3aa-4474-8c24-b07d85406930', u'<built-in method now of type object at 0x37c520>', u'Bert')] (only works with Sqlite - MySQL would throw an error earlier) I think this check in BaseAdapter.represent (dal.py) is the culprit: def represent(self, obj, fieldtype): if type(obj) in (types.LambdaType, types.FunctionType): obj = obj() print type(datetime.datetime.now) in (types.LambdaType, types.FunctionType) >>> False This version lets you use any callable for generating "dynamic" default values (plus it's 3-4 times faster): def represent(self, obj, fieldtype): if callable(obj): obj = obj() I hope this doesn't cause any side effects - at least I could not find any (at this late/early hour)... Thanks