On Jan 27, 5:08 pm, Ole Martin Maeland <olemael...@gmail.com> wrote: > instead of default=now use default = request.now > > also change default = now in modified_on to update=request.now > > regards > Martin >
You are right - that works because request.now is a datetime value. The point is that it should be possible to pass a function as a field's default that yields a new value for each insert (see other ORMS, e.g. Django). uuid.uuid4 is a good example and it actually works out of the box: ... Field('uuid', length=64, default=uuid.uuid4), ... Multiple inserts for the same request should get unique uuids of course, so we need a function here. Some other functions like "datetime.datetime.now" and most probably others don't work the same way leading to inconsistent behaviour. Cheers, Bernd > On Wed, Jan 26, 2011 at 1:36 AM, Bernd Rothert <roth...@googlemail.com>wrote: > > > > > > > > > > > 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 > > -- > Hilsen > Ole Martin > Mob: 95227471