Virtual Fields and table inheritance

115 views
Skip to first unread message

Michele Comitini

unread,
May 5, 2016, 6:44:55 AM5/5/16
to web2py-developers
I got a bad day with this:

db.Table('template_table',  Field.Virtual('virtual_field', lambda r:  r.template_table.id))

db.define_table('real_table', template_table)

sadly the virtual field wants the table name.


I wonder if we can do something here without breaking api? (is still experimental?)

adding a parameter would make sense?

new_row[tablename][f] = v.f(new_row, tablename)
then the virtual field function above would be:

lambda r, tablename: r[tablename].id

or better

new_row[tablename][f] = v.f(new_row[tablename])
then the virtual field function above would be:

lambda r, tablename: r.id

which is limiting access to just the part of record related to the table where the virtual field lives

mic

mcm

unread,
May 18, 2016, 5:26:05 AM5/18/16
to web2py-developers
@niphlod @gi0baro @anthony

Please take a look into this and give feedback ;-)
It is useful to have virtual fields inheritance? does it make sense?

Giovanni Barillari

unread,
May 18, 2016, 11:43:45 AM5/18/16
to web2py-developers
IMHO this would be dangerous since prevent users to use virtual fields and methods on extra values and on selected rows with more than one table.
And will break the current apis.

/Giovanni

mcm

unread,
May 18, 2016, 6:15:55 PM5/18/16
to web2py-developers
Now, if I understand correctly the current state (marked experimental on the book last time I checked), you could  have a virtual field that works within a select and breaks within another one when the joined tables are different? IMHO that is confusing to say the least!

semantically the field is defined inside the table, and not in a query. It makes sense that the only input args  is a record from that specific table where the virtual field belongs.  Then of course the virtual field function could be implemented using a closure that add external state. 
Else we call virtual field something that is more a SELECT EXPRESSION which is a different animal, and as such the definition would belong to the .select() method.

By select expression I mean something like:

select (t1.f1+t2.f2) as vfield from t1, t2

Giovanni Barillari

unread,
May 18, 2016, 7:04:21 PM5/18/16
to web2py-developers
Yes, I was "pissed off" almost like you first times I had to write down row.thetablename.field inside a virtualfield function. 

And this is why I encapsulated them into a wrapper in weppy (http://weppy.org/docs/dev/dal/virtuals#virtual-fields) so the default behaviour is to bind them to the table, but changing the apis means breaking the backward compatibility to any application used them (and weppy too, but that's minor since I can update it).

Anyway, I don't understand how this will solve your problem, since you still have to pass the tablename parameter to the lambda when defining the template table, but this would be different in the other tables, and you will encounter the same problem as before.
In weppy virtualfields are inherited because models do the magic behind the scenes, re-binding the virtual functions to their instance, but doing the same in pydal would be quite a mess (tables are all the same objects).

tl;dr: IMHO inheritance works good when you use classes.

/Giovanni

Michele Comitini

unread,
May 18, 2016, 7:22:38 PM5/18/16
to web2py-developers

that would be a hack just to avoid typing,  yes the function would need to reference the table, but now we know the name:

ex.
def virtfun(r, tname):
    return r[tname].f + 1

but best would have to have base.py do that

i.e. calling virtfun as this:
tname = vfield.table
vfieldvalue = virtfun(r[tname])

so the vfield views only the pertaning part of the record being used to generate the Row  object

then the virtual field function above would be simply defined as such:

def virtfun(r):
   return r.f + 1

in this case only fields from the table where the vfield belongs would be accessible, limiting but IMHO correct as you are not tempted to make a virtual field function that relies on some joined query...




--
-- mail from:GoogleGroups "web2py-developers" mailing list
make speech: web2py-d...@googlegroups.com
unsubscribe: web2py-develop...@googlegroups.com
details : http://groups.google.com/group/web2py-developers
the project: http://code.google.com/p/web2py/
official : http://www.web2py.com/
---
You received this message because you are subscribed to the Google Groups "web2py-developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web2py-develop...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michele Comitini

unread,
May 18, 2016, 7:27:11 PM5/18/16
to web2py-developers
Anyway this thing really drives me nuts.  I may try to find a way to make it straight ... keeping the "wrong" current behavior also

Giovanni Barillari

unread,
May 18, 2016, 7:30:45 PM5/18/16
to web2py-developers
Just to clarify: I'm the first on the line for deprecations and updating code, but this just not seems the "web2py philosophy", so I never proposed changing this. Good luck =)

/Giovanni

Anthony

unread,
May 19, 2016, 6:30:03 AM5/19/16
to web2py-developers
in this case only fields from the table where the vfield belongs would be accessible, limiting but IMHO correct as you are not tempted to make a virtual field function that relies on some joined query...

Why not allow virtual field functions that work on the results of joins? Virtual fields can be defined at any point (i.e., they don't have to be defined with the original model), so if you need a computation based on joined records, you can define the relevant virtual field in the controller where you do the join. The old style virtual fields also work on joins (by design).

Anthony

Michele Comitini

unread,
May 19, 2016, 7:22:13 AM5/19/16
to web2py-developers
and one sets the virtual field as attribute of a Set or of a Table?  On which Table of the ones participating to the join?
It works but looks rather confusing and since then on forces using that table only in specific joins where all attributes can be resolved.
IMHO  they should be binded to Sets or Rowsets

--

Anthony

unread,
May 19, 2016, 12:46:50 PM5/19/16
to web2py-developers
On Thursday, May 19, 2016 at 7:22:13 AM UTC-4, mcm wrote:
and one sets the virtual field as attribute of a Set or of a Table?  On which Table of the ones participating to the join?
It works but looks rather confusing and since then on forces using that table only in specific joins where all attributes can be resolved.

I agree, it isn't the most straightforward, but you do not have to define all virtual fields in the same place as the original table definition. If you are doing a particular join (e.g., in a controller), you can simply define the relevant virtual field dynamically in that one context -- in other contexts, that particular virtual field would not exist. This is how you would do it if you were binding the virtual field directly to the Set or Rows object anyway (i.e., in the context where the Set or Rows object is created, not where the tables are originally defined).
 
IMHO  they should be binded to Sets or Rowsets

Well, we can already do that with old style virtual fields, but they're a bit more cumbersome to define.

Anyway, I don't have a strong opinion on how best to accommodate virtual fields on joins, but whatever we do, we should not break existing code.

Anthony

Massimo DiPierro

unread,
Jun 18, 2016, 5:22:47 PM6/18/16
to web2py-d...@googlegroups.com
Yes. This was by design and a feature.

Massimo DiPierro

unread,
Jun 18, 2016, 5:23:30 PM6/18/16
to web2py-d...@googlegroups.com
I agree with Anthony on this.

Michele Comitini

unread,
Jun 18, 2016, 5:34:35 PM6/18/16
to web2py-developers
@mdp the point is that it seems to me that breaks table inheritance, and you know that "virtual" has a profound meaning in OO wording.
Is there a way to make them inheritable?

Reply all
Reply to author
Forward
0 new messages