Massimo, will you fix the book or web2py source code?
On Wed, Jan 26, 2011 at 12:49 PM, Massimo Di Pierro <massimo.dipie...@gmail.com> wrote: > Good catch. I will fix this asap. > > On Jan 25, 6:36 pm, 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