How to pass a query set string or a string with a select/count to be executed in another controller?

76 views
Skip to first unread message

jcrm...@gmail.com

unread,
May 1, 2019, 5:07:45 AM5/1/19
to web2py-users
Hello,

How to pass a query set string or a string with a select/count to be executed in another controller?

On one controller I create one of these 4 examples:
session.checks = [
       
'db(db.equipment.sn_counter_id == request.args[0]).count()',
        T
('Cannot be deleted while assigned to an equipment.'),
]

session.checks = [
        QUERY_FOR_COUNT,
       
'db.equipment.sn_counter_id == request.args[0]',
        T
('Cannot be deleted while assigned to an equipment.'),
]

session.checks = [
       
'db(db.equipment.depends_on == request.args[0]).select()',
        T
('Cannot be deleted while dependent on an option.'),
]

session.checks = [
        QUERY_FOR_SELECT,
       
'db.equipment.depends_on == request.args[0]',
        T
('Cannot be deleted while dependent on an option.'),
]

and then execute it on another controller using something similar to (of course my example below doesn't work):
            if session.checks[0]:
                session
.flash = session.checks[1]
                redirect
(return_to)

Thanks,

JM

jcrm...@gmail.com

unread,
May 1, 2019, 4:53:25 PM5/1/19
to web2py-users
Got the answer in the Telegram chat. Using eval.
It's a dangerous solution but works.

Dave S

unread,
May 1, 2019, 5:00:27 PM5/1/19
to web2py-users


On Wednesday, May 1, 2019 at 1:53:25 PM UTC-7, jcrm...@gmail.com wrote:
Got the answer in the Telegram chat. Using eval.
It's a dangerous solution but works.

jcrm...@gmail.com

unread,
May 1, 2019, 5:22:11 PM5/1/19
to web2py-users
What do you mean?

I don't want to serialize the query.
And I want the query to only be executed on the desalination controller.

Dave S

unread,
May 1, 2019, 5:43:06 PM5/1/19
to web2py-users
<

On Wednesday, May 1, 2019 at 2:22:11 PM UTC-7, jcrm...@gmail.com wrote:
What do you mean?

I don't want to serialize the query.
And I want the query to only be executed on the desalination controller.


Did you read the reference?

<quote>

You can even build a query (using operators like ==, !=, <, >, <=, >=, like, belongs) and store the query in a variable q such as in:

>>> q = name == 'Alex'

</quote>
 
 

jcrm...@gmail.com

unread,
May 1, 2019, 5:47:53 PM5/1/19
to web2py-users
Yes, I read it..

If you try to save it on a session var (to pass between requests) it will return a pickling error (or not), depending on the query.
I tried to save this
db.equipment.sn_counter_id == request.args[0]
and it returns a pickling error.
Probably because of request.args[0].

Dave S

unread,
May 1, 2019, 8:01:01 PM5/1/19
to web2py-users


On Wednesday, May 1, 2019 at 2:47:53 PM UTC-7, jcrm...@gmail.com wrote:
Yes, I read it..

If you try to save it on a session var (to pass between requests) it will return a pickling error (or not), depending on the query.
I tried to save this
db.equipment.sn_counter_id == request.args[0]
and it returns a pickling error.
Probably because of request.args[0].


Does copying request.args[0] to a local [string] variable help?

/dps
 

jcrm...@gmail.com

unread,
May 2, 2019, 5:42:15 AM5/2/19
to web2py-users
Can't do that. As I told you the query has to be executed on the destination.

Dave S

unread,
May 2, 2019, 1:00:10 PM5/2/19
to web...@googlegroups.com


On Thursday, May 2, 2019 at 2:42:15 AM UTC-7, jcrm...@gmail.com wrote:
Can't do that. As I told you the query has to be executed on the destination.

Huh?  I'm confused.   You're trying to pass a query (not the results of the select), and having trouble pickling request.args[0].  I'm guessing that the type of object that request.args is why there's a pickling error.  So copy the string you're interested in to a simple[r] local string variable, form the query with that, and pickle that.

If the request.args[0] that you want to use in the query isn't known when you set the session variable because it is the request.args[0] of the later request, then yeah, you can't pass it in the session variable.  In that case, I wouldn't try to pass the query; I'd pass the table name and the field, and maybe the error message.  Those are all simple string arguments.

Another approach, since these look a lot like validators to me, is to forget about using session, and simply define the functions in your model, which puts the function into your name space.

I have to admit that when I read your questions, I am sometimes wpndering if you are trying to do things in a much more complicated way than necessary.  It is true that I don't know your use cases or workflow, or the particulars of your "problem space", and that the applications I do tend to be simple, so my ignorance is probably why I get that impression, but your questions seem to stand out in this forum.  However, you also have demonstrated both a perseverance and a problem solving ability, so I admire what you've done.

/dps

Anthony

unread,
May 2, 2019, 11:01:00 PM5/2/19
to web2py-users
On Wednesday, May 1, 2019 at 4:53:25 PM UTC-4, jcrm...@gmail.com wrote:
Got the answer in the Telegram chat. Using eval.
It's a dangerous solution but works.

So dangerous you probably shouldn't do it.

Also, do you want to use the value of request.args[0] from the original request where the query is saved to the session, or from the subsequent request where the query is retrieved from the session? Storing the query object itself would achieve the former, whereas using eval would achieve the latter.

In either case, the best approach is just to store the data needed to generate the query in the session (e.g., table and field name, and the request.args value). Then construct the query in the second action. There is no need to store the query itself (or a text representation of the query code).

Anthony

jcrm...@gmail.com

unread,
May 3, 2019, 4:22:58 AM5/3/19
to web2py-users
request.args[0] from the destination request. Yes, eval is the only way to solve this, but because it is so dangerous, I dismissed the idea.

The original idea was to have a shared function (in another controller) that would be used by several controllers, each with specific queries that would be passed to the destination using session. The queries would be passed as strings to be executed only at the destination.

Due to the dangerous nature of eval and been the only solution, I've given up on that and repeated the code in each table controller's (with the specific query for each of course).

Thank you all for the help.

Anthony

unread,
May 3, 2019, 7:42:05 AM5/3/19
to web2py-users
It might help to show some code. Why don't you just put the shared function in a model or module and call it directly from each controller?

jcrm...@gmail.com

unread,
May 3, 2019, 8:35:53 AM5/3/19
to web2py-users
That was what I was trying to do.
The problem is that the queries that were going to be executed in the destination (shared function) vary according to the requesting controller. The query string passed through the session would solve this, but because the only way to execute it in the destination would be to use eval, I dismissed the idea.

Anthony

unread,
May 4, 2019, 11:19:42 AM5/4/19
to web2py-users
In each controller:

from mymodule import shared_function
rows
= shared_function(pass, some, args)

Not clear why you instead need to use the session and have another controller action involved.

Anthony

jcrm...@gmail.com

unread,
May 4, 2019, 4:58:15 PM5/4/19
to web...@googlegroups.com
Let me explain the scenario.

I have several pairs of controllers/views (eg. opt, opt_cat, equip) that each manage a single table because they have different characteristics.

And I have several pairs of controllers/views that are shared (eg. single_equip and table_management) that manage several different tables each (all the tables each manages have the same characteristics). I use session vars to indicate, among other things, the table name to be managed.

This all works fine.

Now I must add a new controller/view pair called get_approval to require a supervisor password to allow an operator to delete (inactivate really) a record of any of the above tables. This action is started by the operator pressing the "Delete" button on the grid that shows the table in one of the above mentioned controller/view pairs (single-table opt, opt_cat... and shared single_equip and table_management).
Bare in mind that each table has different checks to be made before allowing the "deletion".

So the solutions I tried were:
1. Use a session var to pass the deletion check query (as a string, not the results) so that the get_approval would execute the query. This works, but because it uses eval I dismissed the idea.
2. I created a function called deletion_checks in each of the controllers. I assigned the function to a session var hopping that I could then execute it in the get_approval, but unfortunately it is not pickleable, therefore it doesn't work.
3. I repeated the get_approval function in each of the controllers. This works fine, but if I need to make change, I must propagate the change to all controllers. Not a good solution but the "least bad" working solution.

The solution you suggest I didn't try because I think a controller with a view doesn't accept function args (only request.args and request.vars if I'm not mistaken) and I need to pass it the deletion_checks function "pointer" so that get_approval executes it (and I remind you that the deletion_checks function is different for each table).

Any ideas?

Thanks.

jcrm...@gmail.com

unread,
May 4, 2019, 4:59:26 PM5/4/19
to web2py-users
I forgot to say on the previous message that if you need I can show you the code.


sábado, 4 de Maio de 2019 às 16:19:42 UTC+1, Anthony escreveu:
Reply all
Reply to author
Forward
0 new messages