Re: [web2py] Re: Callable as Field.default

2011-01-28 Thread Vinicius Assef
Massimo, good news to me.

It shoud be in the book!



On Fri, Jan 28, 2011 at 12:32 PM, Massimo Di Pierro
 wrote:
> The fact is, you can do both. If you want the values to be evaluated
> on insert, just do
>
> Field(...,default=lambda: f())
>
> instead of
>
> Field(...,default=f())
>
> If you want lazy evaluation you have to be explicit.
>
> On Jan 27, 4:51 pm, Vinicius Assef  wrote:
>> On Thu, Jan 27, 2011 at 3:54 PM, Bernd Rothert  
>> wrote:
>>
>> > Multiple inserts for the same request should get unique uuids of
>> > course, so we need a function here.
>>
>> I faced this problem some time ago.
>>
>> Default values defined in models are not assigned in INSERT time, but
>> in REQUEST time.
>>
>> So, if you have a loop with insert inside it, all records will have
>> the same default values.
>>
>> This is a web2py feature, in spite my thought explained that time that
>> it should be different. When you talk about database, default values
>> should be evaluated as in SQL INSERT: in insert time.
>>
>> --
>> Vinicius Assef.


Re: [web2py] Re: Callable as Field.default

2011-01-27 Thread Vinicius Assef
On Thu, Jan 27, 2011 at 3:54 PM, Bernd Rothert  wrote:
>
> Multiple inserts for the same request should get unique uuids of
> course, so we need a function here.

I faced this problem some time ago.

Default values defined in models are not assigned in INSERT time, but
in REQUEST time.

So, if you have a loop with insert inside it, all records will have
the same default values.

This is a web2py feature, in spite my thought explained that time that
it should be different. When you talk about database, default values
should be evaluated as in SQL INSERT: in insert time.

--
Vinicius Assef.


Re: [web2py] Re: Callable as Field.default

2011-01-26 Thread Vinicius Assef
Massimo,
will you fix the book or web2py source code?



On Wed, Jan 26, 2011 at 12:49 PM, Massimo Di Pierro
 wrote:
> Good catch. I will fix this asap.
>
> On Jan 25, 6:36 pm, Bernd Rothert  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: '>
>> Umm,...
>>
>> db.executesql(db(db.person)._select())>>> [(1,
>>
>>   u'b35cc052-3800-42a9-b7eb-bb9bc8ada271',
>>   u'',
>>   u'Ernie'),
>>  (2,
>>   u'003ab438-f3aa-4474-8c24-b07d85406930',
>>   u'',
>>   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