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

Reply via email to