How to use virtualfields?

13 views
Skip to first unread message

Iceberg

unread,
Apr 5, 2010, 3:51:27 AM4/5/10
to web2py-users
Hi there,

I search virtualfields in http://www.web2py.com/book but found
nothing.

So I read this post instead: https://groups.google.com/group/web2py/browse_frm/thread/d59ee3d6c2e6d836?tvc=1

But I found that
db.table.virtualfields.add(ComputedFields())
doesn't work.

Only this work:
rows.setvirtualfields(table=ComputedFields())

Does the former syntax really supposed to exist?

I am using web2py 1.75.4

Regards,
Iceberg

Thadeus Burgess

unread,
Apr 5, 2010, 4:00:06 AM4/5/10
to web...@googlegroups.com
I think its

db.table.virtualfields.append()

-Thadeus

> --
> You received this message because you are subscribed to the Google Groups "web2py-users" group.
> To post to this group, send email to web...@googlegroups.com.
> To unsubscribe from this group, send email to web2py+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/web2py?hl=en.
>
>

Iceberg

unread,
Apr 5, 2010, 4:09:01 AM4/5/10
to web2py-users
Actually I did notice that typo, I tried the append() already, my code
is:

class VirtualFields:
def profit(self): return self.Orders.income - self.Orders.cost
db.Orders.virtualfields.append(VirtualFields())

this line runs fine, but later when I need to access a virtual field,
an exception is raised:

File "C:\DOWNLOAD\google_appengine\web2py\gluon\sql.py", line 658,
in __getitem__
return dict.__getitem__(self, key)
KeyError: 'profit'

Ideas? Thanks.

-Iceberg

On Apr5, 12:00pm, Thadeus Burgess <thade...@thadeusb.com> wrote:
> I think its
>
> db.table.virtualfields.append()
>
> -Thadeus
>
>
>
> On Sun, Apr 4, 2010 at 10:51 PM, Iceberg <iceb...@21cn.com> wrote:
> > Hi there,
>

> > I search virtualfields inhttp://www.web2py.com/bookbut found
> > nothing.
>
> > So I read this post instead:  https://groups.google.com/group/web2py/browse_frm/thread/d59ee3d6c2e6...

mdipierro

unread,
Apr 5, 2010, 4:18:07 AM4/5/10
to web2py-users
I just did this as a test and it worked:

>>> db=DAL('sqlite:memory:')
>>> db.define_table('test',Field('quantity','integer'))
>>> class VirtualFields():
... def profit(self): return self.test.quantity*100
>>> db.test.virtualfields.append(VirtualFields())
>>> db.test.insert(quantity=5)
1
>>> rows=db(db.test.id>0).select()
>>> for row in rows: print row
...
<Row {'update_record': <function <lambda> at 0x1b8dbb0>, 'profit':
500, 'id': 1, 'delete_record': <function <lambda> at 0x1b8dab0>,
'quantity': 5}>

Sure you are running an updated version of web2py? Which os? which
version?

Iceberg

unread,
Apr 5, 2010, 8:13:37 AM4/5/10
to web2py-users
Old problem solved, new problem arises.

There is a somewhat obvious difference which I did not notice before.

(1) db.table.virtualfields.append(ComputedFields())
This need to be executed BEFORE db().select(), otherwise it will NOT
affect the select result rows.

(2) rows.setvirtualfields(table=ComputedFields())
This of course can only be used AFTER you've got the rows (and you
can't possibly go to the wrong way.)

However, there must be some more subtle difference I don't know yet.
Even I use (1) BEFORE my db().select(), I found that is much slower
(perhaps due to some lazy function call). And worse, (1) can't support
"virtual field has SAME name as real field", while (2) can. My code
looks like:

class VirtualFields:
distributors=db().select(db.Distributor.id,db.Distributor.name,
cache=(cache.ram,3600*24)).as_dict()
def income(self):
# round the real field "income" into "per thousand" unit
return self.mytable.income / 1000.0
def distributor(self):
# tend to change real field "distributor" from id to its
name
return self.distributors.get(
self.Orders.distributor,{}).get('name')

So I think I have to stick to usage (2), do I?

BTW, I am using the latest web2py trunk on Windows XP.

Regards,
Iceberg

On Apr5, 12:18pm, mdipierro <mdipie...@cs.depaul.edu> wrote:
> I just did this as a test and it worked:
>
> >>> db=DAL('sqlite:memory:')
> >>> db.define_table('test',Field('quantity','integer'))
> >>> class VirtualFields():
>
> ...     def profit(self): return self.test.quantity*100>>> db.test.virtualfields.append(VirtualFields())
> >>> db.test.insert(quantity=5)
> 1
> >>> rows=db(db.test.id>0).select()
> >>> for row in rows: print row
>
> ...
> <Row {'update_record': <function <lambda> at 0x1b8dbb0>, 'profit':
> 500, 'id': 1, 'delete_record': <function <lambda> at 0x1b8dab0>,
> 'quantity': 5}>
>
> Sure you are running an updated version of web2py? Which os? which
> version?
>

> > > On Sun, Apr 4, 2010 at 10:51 PM, Iceberg <iceb...@21cn.com> wrote:


> > > > Hi there,
>
> > > > I search virtualfields inhttp://www.web2py.com/bookbutfound
> > > > nothing.
>
> > > > So I read this post instead:  https://groups.google.com/group/web2py/browse_frm/thread/d59ee3d6c2e6...
>
> > > > But I found that

> > > >  db.table.virtualfields.append(ComputedFields())

mdipierro

unread,
Apr 5, 2010, 3:41:00 PM4/5/10
to web2py-users
You know web2y better than me. I had forgotten about Rows.as_dict()

If option 2 works with you, use 2.

Thadeus Burgess

unread,
Apr 5, 2010, 3:41:58 PM4/5/10
to web...@googlegroups.com
Its slower because each function is executed with the query. So what
happens is when you get your rows object, it is the value of the
function, not the function.

If you wrap all of your functions in a lambda as a "lazy" function,
then it will increase the speed

please look at http://thadeusb.com/weblog/view/web2py_virtualfields_as_an_orm_an_sqlalchemy_approach
for more information

-Thadeus

Reply all
Reply to author
Forward
0 new messages