Op woensdag 13 augustus 2014 15:00:38 UTC+2 schreef Anthony:
>
> def new_style_virtual_field_test():
>
> db = DAL('sqlite:memory',pool_size=1)
>> db.define_table('myorder',
>> Field('a','integer'),
>> Field('b','integer')
>> )
>> db.myorder.c = Field.Virtual(lambda row:row.a * row.b)
>> db.myorder.insert(a=2,b=3)
>> return db().select(db.myorder.ALL).first().as_json()
>> # {"a": 2, "id": 1, "b": 3}
>>
>
> Are you sure that's the exact code you have run, because row.a * row.b is
> not the correct syntax and should result in an exception as soon as you do
> a select.
>
It is, just tested this. I'm using 2.9.5-stable+timestamp.2014.03.16.02.35.39
using python 2.7.3
> Instead, it should be:
>
>
db.myorder.c = Field.Virtual('c', lambda row: row.myorder.a * row.myorder.b)
>
> In the function, you must include the table name when accessing fields in
> the row. Also, note that even when creating the virtual field via
> assignment, you should still specify the name of the virtual field within
> Field.Virtual() -- otherwise the "name" attribute of the virtual field will
> be set to "unknown", which may cause problems in some contexts.
>
Thanks for the enlightenment. I've tried your change, and now it gives me
the proper result. But i don't get your remark about the name attribute. I
can't find that in the book for new style virtual classes, can you offer me
a pointer? When looking at ">>> db.item.total_price = Field.Virtual(lambda
row: row.unit_price*row.quantity)" from the book (mind the table name not
being used here either) i thought the name assignment would be automatic by
using db.myorder.c
def new_style_virtual_field_test_anthony():
db = DAL('sqlite:memory',pool_size=1)
db.define_table('myorder',
Field('a','integer'),
Field('b','integer')
)
db.myorder.c = Field.Virtual(lambda row:row.myorder.a * row.myorder.b)
# added tablenames in the lambda
db.myorder.insert(a=2,b=3)
return db().select(db.myorder.ALL).first().as_json()
# {"a": 2, "c": 6, "b": 3, "id": 1}
# hurray
return db().select(db.myorder.a, db.myorder.b,
>> db.myorder.c).first().as_json()
>> # <class 'sqlite3.OperationalError'> no such column: None.unknown
>> # (self=<gluon.dal.SQLiteAdapter object>, *a=('SELECT myorder.a,
>> myorder.b, None.unknown FROM myorder;',), **b={})
>>
>> # where has my C field gone to?
>>
>
> Virtual fields are not stored in the database but are calculated after
> records are pulled from the database, so they are not to be listed in the
> call to .select().
>
Can a notimplemented exception be justified in such a case?
> def old_style_virtual_field_test1():
>> db = DAL('sqlite:memory',pool_size=1)
>> db.define_table('myorder',
>> Field('a','integer'),
>> Field('b','integer')
>> )
>> class MyVirtualFields(object):
>> def c(self):
>> return self.myorder.a * self.myorder.b
>> db.myorder.virtualfields.append(MyVirtualFields())
>> db.myorder.insert(a=2,b=3)
>> # return db().select(db.myorder.ALL).first().as_json()
>> # {"a": 2, "id": 1, "b": 3}
>> # where is c?
>>
>
> Don't know. When I run the exact code above, I get:
>
> {"a": 2, "c": 6, "b": 3, "id": 1}
>
>
My bad, i get the same.
return db().select(db.myorder.a, db.myorder.b,
>> db.myorder.c).first().as_json()
>> # AttributeError: 'Table' object has no attribute 'c'
>>
>> # it doesn't ? I thought i declared to be virutally present
>>
>
> Old style virtual fields work differently -- they don't result in
> individual "field" attributes being added to the table object. Rather, they
> are stored in the "virtualfields" attribute of the table.
>
def old_style_virtual_field_test1_anthony():
db = DAL('sqlite:memory',pool_size=1)
db.define_table('myorder',
Field('a','integer'),
Field('b','integer')
)
class MyVirtualFields(object):
def c(self):
return self.myorder.a * self.myorder.b
db.myorder.virtualfields.append(MyVirtualFields())
db.myorder.insert(a=2,b=3)
return db().select(db.myorder.a, db.myorder.b).first().as_json()
# Don't include the virtual fields on .select, they're implied
# {"a": 2, "c": 6, "b": 3}
# hurray!
I removed the db.myorder.c from the select and not it works. Above is the
working sample left here for reference - this way it's basically the same
as the above statement using old style virtual fields.
> db.myorder.setvirtualfields(myorder=MyVirtualFields())
>> # <type 'exceptions.AttributeError'> 'Table' object has no attribute
>> 'setvirtualfields'
>> # maybe a bit more clarity in the documentation would be nice. I
>> understand the purpose
>> # but it's easily overlooked.
>>
>
> The book seems fairly clear to me on this point. The only example it shows
> using .setvirtualfields() is in the context of creating virtual fields on
> the result of a join, with the following code:
>
> rows.setvirtualfields(order_item=MyVirtualFields())
>
> It then says (highlights added):
>
> Notice how in this case the syntax is different. The virtual field
> accesses both self.item.unit_price and self.order_item.quantity which
> belong to the join select. The virtual field is attached to the rows of
> the table using the setvirtualfields method of the rows object.
>
>
As mentioned, it's easily overlooked but the documentation is complete. I'm
not complaining or saying it's wrong, just letting a documentation writer
in on some reader feedback. Thanks for your clarification here.
> rows = db(db.myorder).select()
>> # now i have to apply them after selecting? That's counter intuitive
>> # i thought it would be in the model, not the controller
>> rows.setvirtualfields(myorder=MyVirtualFields())
>> # also note the setvirtualfields has to be applied to the rows, not
>> to a single row.
>>
>
> There is no need to use .setvirtualfields() in the above example given
> that you are selecting from a single table. The primary purpose of that
> method is when you want to apply virtual fields to the result of a join of
> multiple tables (so, you must apply the virtual fields to the rows rather
> than to an individual table).
>
Indeed, that's why i was suprised. But i know understand more clearly what
went wrong in the earlier examples, and would never use the code in the
above example in such a case if something else is possible.
Thank you Anthony.
--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to the Google Groups
"web2py-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.