I've been experimenting with creating virtual fields and have come across what may be a possible bug when they are created via old style (class definitions).
I created a small table with 3 fields (ID, Name and dob). I've added some virtual fields to compute the age in days using all the options defined in the docs. http://web2py.com/books/default/chapter/29/6?search=virtual+fields#Virtual-fields I see the following (unexpected results) (See the test code below) 1) For old style (class defined vf's) - Results returned from virtual fields computations are incorrect. The same value for all records is shown - (the last value in the table is displayed in each case) 2) For New style vfs: - Correct results are returned: Is there bug in my code, or has anyone seen this behaviour before? Below is sample o/p from my tests and the test program Vclass : name: fred; dayage: 34427 Vclass : name: joe; dayage: 18730 Vclass : name: harry; dayage: 15382 Name: fred; DOB: 1917-11-10 12:00:00; **** Using VF Class: Age (class): 15382; Age(Lazy); 15382; Age(Lazy Lambda): 15382 **** Using New Style VFs: Age (new style): 34427; Age(new style (Lazy)); 34427 Name: joe; DOB: 1960-11-01 12:00:00; **** Using VF Class: Age (class): 15382; Age(Lazy); 15382; Age(Lazy Lambda): 15382 **** Using New Style VFs: Age (new style): 18730; Age(new style (Lazy)); 18730 Name: harry; DOB: 1970-01-01 12:00:00; **** Using VF Class: Age (class): 15382; Age(Lazy); 15382; Age(Lazy Lambda): 15382 **** Using New Style VFs: Age (new style): 15382; Age(new style (Lazy)); 15382 ****** Test Code ****** import os, sys sdir = '/home/web2py' sys.path.append(sdir) try: from gluon import DAL, Field except ImportError as err: print('gluon path not found') # target db - sqlite db = DAL("sqlite://mydb.sqlite") # define view/table ################## # # db view testing # define some virtual fields here (psa stale, fustale) # ################## db.define_table('person', Field('name', type='string'), Field('dob', type='datetime'), migrate=False) import datetime now = datetime.datetime.now() # define new style virtual fields - age in days (aid) db.person.virtual_aid =Field.Virtual(lambda row : (now - row.person.dob).days ) db.person.lazy_aid =Field.Lazy(lambda row : (now - row.person.dob).days ) # lambda version class MyVf(object): # define a new virtual field value def vfclass_aid(self): self.daycount = (now - self.person.dob).days print 'Vclass : dayage: %s' %self.daycount return lambda : self.daycount # define a lazy vf def vfclass_lazy_aid(self): def lazy(self=self): return (now - self.person.dob).days return lazy # define a lazy lambda vf def vfclass_lazy_lambda_aid(self): return lambda self= self: (now - self.person.dob).days if __name__ == "__main__": import datetime dtstart = datetime.datetime.now() print '\n>>>>Starting at: %s <<<<\n' %dtstart.ctime() # create virtual field (using a class) db.person.virtualfields.append(MyVf()) for item in db(db.person).select(): print '\nName: %s; DOB: %s;'%(item.name, item.dob) print '\t **** Using VF Class: \t\tAge (class): %s;\t\tAge(Lazy); %s;\t Age(Lazy Lambda): %s' \ %(item.vfclass_aid(), item.vfclass_lazy_aid(), item.vfclass_lazy_lambda_aid() ) print '\t **** Using New Style VFs: \tAge (new style): %s; \tAge(new style (Lazy)); %s ' \ %(item.virtual_aid, item.lazy_aid()) dtend = datetime.datetime.now() print '\n>>>>Ending at: %s <<<<\n' %dtend.ctime()