How to use requires with list:reference

159 views
Skip to first unread message

Mandar Vaze

unread,
Jun 10, 2014, 10:05:21 AM6/10/14
to web...@googlegroups.com
when using default 'list:reference mytable' all the entries from mytable are shown in the dropdown (when using SQLFORM.grid)
I want to show the list in the drop down after applying some filters

Here is an example :

db.define_table('parent',
               
Field('fname', 'string'),
               
Field('lname', 'string'),
                format
='%(fname)s %(lname)s'
               
)

def get_parents(lname):
   
return db(db.parent.lname == lname)

db
.define_table('child',
               
Field('first_name', 'string'),
               
Field('last_name', 'string'),
               
Field('parents', 'reference parent',
                      requires
=IS_IN_DB(lambda row: get_parents(row.child.last_name), 'parent._format')),
                format
='%(fname)s %(lname)s'
               
)


Here the idea is the when associating an entry from parent table - only those values are shown where last name of child matches that of the parent
Obviously the example is "made up" - real scenario is bit complicated - but I am getting following error :

AttributeError: 'function' object has no attribute 'db'



web2py™ Version 2.9.5-stable+timestamp.2014.03.16.02.35.39

Traceback

Traceback (most recent call last):
File "/path/to/web2py/gluon/restricted.py", line 220, in restricted
exec ccode in environment
File "/path/to/web2py/applications/parents/controllers/appadmin.py", line 674, in <module>
File "/path/to/web2py/gluon/globals.py", line 385, in <lambda>
self._caller = lambda f: f()
File "/path/to/web2py/applications/parents/controllers/appadmin.py", line 153, in insert
form = SQLFORM(db[table], ignore_rw=ignore_rw)
File "/path/to/web2py/gluon/sqlhtml.py", line 1151, in __init__
inp = self.widgets.options.widget(field, default)
File "/path/to/web2py/gluon/sqlhtml.py", line 273, in widget
options = requires[0].options()
File "/path/to/web2py/gluon/validators.py", line 559, in options
self.build_set()
File "/path/to/web2py/gluon/validators.py", line 531, in build_set
table = self.dbset.db[self.ktable]
AttributeError: 'function' object has no attribute 'db'

I am OK to use "list:string" with IS_IN_SET() as well - but I am unable to use "lambda row: get_parents(row.child.last_name)"
I get "function is not iterable" error (Off course I will change get_parents() function to return list of strings based on my query)

-Mandar

Anthony

unread,
Jun 10, 2014, 10:23:22 AM6/10/14
to web...@googlegroups.com
The first argument to IS_IN_DB must be a DAL object or a Set object -- it cannot be a function.

Anthony

Mandar Vaze / मंदार वझे

unread,
Jun 10, 2014, 12:51:20 PM6/10/14
to web...@googlegroups.com
On Tue, Jun 10, 2014 at 7:53 PM, Anthony <abas...@gmail.com> wrote:
The first argument to IS_IN_DB must be a DAL object or a Set object -- it cannot be a function.

Right, but is there a way to achieve what I am trying to do ? an example would help.
Can/should I use IS_IN_SET ? (I got different error mentioned above)

I think I'm missing something important

Thanks,
-Mandar


--
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 a topic in the Google Groups "web2py-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/web2py/nDBOL7w6qB4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Anthony

unread,
Jun 10, 2014, 1:53:13 PM6/10/14
to web...@googlegroups.com
Assuming you have a particular parent last name, it would be:

IS_IN_DB(db(db.parent.lname == last_name), 'parent.id', db.parent._format, multiple=True)

Anthony
To unsubscribe from this group and all its topics, send an email to web2py+unsubscribe@googlegroups.com.

Mandar Vaze / मंदार वझे

unread,
Jun 11, 2014, 6:49:56 AM6/11/14
to web...@googlegroups.com
On Tue, Jun 10, 2014 at 11:23 PM, Anthony <abas...@gmail.com> wrote:
Assuming you have a particular parent last name, it would be:

IS_IN_DB(db(db.parent.lname == last_name), 'parent.id', db.parent._format, multiple=True)


Above would work for a "fixed" last name. But I need it to work with "lambda" - where last_name is same as that of the child

-Mandar



 
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.

Anthony

unread,
Jun 11, 2014, 8:30:01 AM6/11/14
to web...@googlegroups.com
Are you saying you want the user to enter a last name for the child and then have the drop-down dynamically updated with the list of parents with the entered last name? If so, obviously that cannot be done at the time the form is generated on the server because you don't know what name the user will enter in the form. You'll instead have to handle this with Javascript in the browser, possibly with an Ajax call back to the server to populate the list (unless the list of parents is small enough to send to the browser with the initial page load).

Anthony

Mandar Vaze / मंदार वझे

unread,
Jun 12, 2014, 1:45:26 AM6/12/14
to web...@googlegroups.com
Anthony,

Let me say that you have been tremendous help.

On Wed, Jun 11, 2014 at 6:00 PM, Anthony <abas...@gmail.com> wrote:
Are you saying you want the user to enter a last name for the child and then have the drop-down dynamically updated with the list of parents with the entered last name? If so, obviously that cannot be done at the time the form is generated on the server because you don't know what name the user will enter in the form.

Hmm.. I did not thing of that.
Actually I was trying only "Edit" option - where last name of the child is known, but parent information is not populated.
Did not think of "New" scenario - my bad.
 
You'll instead have to handle this with Javascript in the browser, possibly with an Ajax call back to the server to populate the list 
(unless the list of parents is small enough to send to the browser with the initial page load).

Makes sense. In that case :

should I even use "reference parent" ? Cause I think it will automatically create and populate the widget for me (which I think I will need to hide somehow ?)

-Mandar

Anthony

unread,
Jun 12, 2014, 7:27:50 AM6/12/14
to web...@googlegroups.com

Are you saying you want the user to enter a last name for the child and then have the drop-down dynamically updated with the list of parents with the entered last name? If so, obviously that cannot be done at the time the form is generated on the server because you don't know what name the user will enter in the form.

Hmm.. I did not thing of that.
Actually I was trying only "Edit" option - where last name of the child is known, but parent information is not populated.
Did not think of "New" scenario - my bad.

In the "edit" scenario, you do have the child last name, so you can take the approach I showed, though you have to set the validator after you retrieve the relevant record. So you would do something like:

child_record = db.child([some id])
db
.child.parents.requires = IS_IN_DB(db(db.parent.lname = child_record.last_name), ...)
edit_form
= SQLFORM(db.child, record=child_record)
  
You'll instead have to handle this with Javascript in the browser, possibly with an Ajax call back to the server to populate the list 
(unless the list of parents is small enough to send to the browser with the initial page load).

Makes sense. In that case :

should I even use "reference parent" ? Cause I think it will automatically create and populate the widget for me (which I think I will need to hide somehow ?)

You still want it to be a reference field. If you don't want the default widget associated with the IS_IN_DB validator, you can always put it in a list (which suppresses the drop-down list widget):

    Field('parents', 'list:reference parent', requires=[IS_IN_DB(...)])

Anthony
 

-Mandar

Mandar Vaze / मंदार वझे

unread,
Jun 14, 2014, 5:21:17 AM6/14/14
to web...@googlegroups.com
This is brilliant !!
Thanks a LOT Anthony

What I ended up doing is :

if request.args(0) == "edit":
    db.child.parent.requires = IS_IN_DB(.....)

In my actual setup - user does not create new record - so "new" is not an issue for me.

-Mandar


--
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 a topic in the Google Groups "web2py-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/web2py/nDBOL7w6qB4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages