Virtual fields

38 views
Skip to first unread message

Tom Clerckx

unread,
Jun 15, 2025, 5:51:50 PM6/15/25
to py4web
Something I'm not getting concerning Virtual Fields....

Test 1 - following the example in the py4web DAL section:
def total_price(row):
logger.warning(f"ROW: {row}")
try:
price = row.item.unit_price * row.item.quantity
except Exception as inst:
logger.warning(f"Exception: {inst}")
price = -1
logger.warning(f"RETURN price: {price}")
return price

db.define_table('item',
Field('unit_price', 'double'),
Field('quantity', 'integer'))

db.item.total_price = Field.Virtual(lambda row: total_price(row))


The total price of the virtual field is set to "-1" and I'm getting the following logs:
2025-06-15 23:39:45,171 - WARNING - models.py:63 - ROW: <Row {'item': {'id': 1, 'unit_price': 15.0, 'quantity': 5}}>
2025-06-15 23:39:45,172 - WARNING - models.py:69 - RETURN price: 75.0
2025-06-15 23:39:45,175 - WARNING - models.py:63 - ROW: {'id': 1, 'unit_price': '15.00', 'quantity': 5}
2025-06-15 23:39:45,175 - WARNING - models.py:67 - Exception: 'dict' object has no attribute 'item'
2025-06-15 23:39:45,175 - WARNING - models.py:69 - RETURN price: -1

So the function seems to be called twice with two different 'row' arguments....

Test 2:

def total_price_new(row):
logger.warning(f"ROW: {row}")
price = float(row['unit_price']) * int(row['quantity'])
logger.warning(f"RETURN price: {price}")
return price

db.define_table('item',
Field('unit_price', 'double'),
Field('quantity', 'integer'))

db.item.total_price = Field.Virtual(lambda row: total_price_new(row))

I'm getting the correct price, and the following logging:
2025-06-15 23:20:21,605 - WARNING - models.py:72 - ROW: <Row {'item': {'id': 1, 'unit_price': 15.0, 'quantity': 5}}>
2025-06-15 23:20:21,608 - WARNING - models.py:72 - ROW: {'id': 1, 'unit_price': '15.00', 'quantity': 5}
2025-06-15 23:20:21,608 - WARNING - models.py:74 - RETURN price: 75.0


In this case the function seems to be called twice, but only returning the last (correct) value....

Can someone explain?

Tom Clerckx

unread,
Jun 15, 2025, 6:25:25 PM6/15/25
to py4web
Update on Test 2:

total_price_new seems to also cause an exception in the first call, which seems to be handled elsewhere...
This explains why I'm not seeing the first "RETURN price" log-line.

I know Virtual Fields are marked as 'experimental'.
Maybe some additional "gotcha's" about it could be added in the documentation?



Reply all
Reply to author
Forward
0 new messages