What's up with calling DTML methods with arguments?
Scenario: I have a GUF based authentication system that uses a SQL database to store user profiles. The primary key of the user table is a serial number, so my users can change there username anytime without throwing the tables into a mess, but usernames are otherwise used as a unique ID for a user, so I need to do a name to user_id lookup before doing most queries. I've also got it set up to handle different password hash methods so I can migrate to a new one if the present one sucks - to make this easy I've got a DTML method called encodePassword that takes a password and the (typically acquired) pwd_format property and gets the appropriate external method to turn it into the password hash. So in my password change report I want to do something like this: (name and new_password arrive from the request, pwd_format is an acquired default) <dtml-call "sql_change_password( user_id=sql_get_user_id(name=name), password=encodePassword(password=new_password), pwd_format=pwd_format )"> But I can't because Zope throws a fit about infinite recursion. Bummer. Ok, how about this: <dtml-let password="encodePassword(password=new_password)" user_id="sql_get_user_id(name=name)"> <dtml-call "sql_change_password( user_id=user_id, password=password, pwd_format=pwd_format)"> </dtml-let> That doesn't work either. It seems that when I pass arguments to the method encodePassword, it ceases to acquire anything else from the environment, including my default pwd_format value, and all the external methods that live in the same folder. This is a pain. No arguments, it acquires, give it arguments, it doesn't. If I wanted it to not acquire things from the environment I'd use the <dtml-with ... only> container, but someone has made that call it seems. So how do I supply a method with an argument and tell it to look in it's folder for other properties and methods to acquire? Am I forever doomed to wrap annoying <dtml-let> containers around all of the methods that I want to acquire properties from the rest of Zope? John.
On Tue, 22 Feb 2000, John Morton wrote:
This is a pain. No arguments, it acquires, give it arguments, it doesn't. If I wanted it to not acquire things from the environment I'd use the <dtml-with ... only> container, but someone has made that call it seems. So how do I supply a method with an argument and tell it to look in it's folder for other properties and methods to acquire? Am I forever doomed to wrap annoying <dtml-let> containers around all of the methods that I want to acquire properties from the rest of Zope?
Not really ... many times abit of reorganization of your Folder structure will do the trick. If I understand your case correctly, you have a folder, lets say "utilities" and you want to be able to call methods in that folder but those methods need to acquire additional properties from Folder "utilities". I would do something like: <dtml-var "utilities.convpasswd(utilities,_,password=new_password, ...)"> and do not pass that would be acquired automatically ... I hope it is useful Pavlos
Pavlos Christoforou writes:
On Tue, 22 Feb 2000, John Morton wrote:
Not really ... many times abit of reorganization of your Folder structure will do the trick. If I understand your case correctly, you have a folder, lets say "utilities" and you want to be able to call methods in that folder but those methods need to acquire additional properties from Folder "utilities". I would do something like:
Actually all of the methods are in the same folder.
<dtml-var "utilities.convpasswd(utilities,_,password=new_password, ...)">
So what's the mystical object that I need to pass that would mean 'the current folder'; <dtml-var "encodePassword(object_that_is_the_current_folder,_,password=new_password, ...)">
and do not pass that would be acquired automatically ...
The problem is _if_ I pass anything, then nothing is acquired automatically. John.
On Tue, Feb 22, 2000 at 03:20:04PM +1300, John Morton wrote:
Pavlos Christoforou writes:
On Tue, 22 Feb 2000, John Morton wrote:
Not really ... many times abit of reorganization of your Folder structure will do the trick. If I understand your case correctly, you have a folder, lets say "utilities" and you want to be able to call methods in that folder but those methods need to acquire additional properties from Folder "utilities". I would do something like:
Actually all of the methods are in the same folder.
<dtml-var "utilities.convpasswd(utilities,_,password=new_password, ...)">
So what's the mystical object that I need to pass that would mean 'the current folder';
<dtml-var "encodePassword(object_that_is_the_current_folder,_,password=new_password, ...)">
_.None should work: <dtml-var "_.None,_,password=new_password, ...)"> -- Stephen Pitts smpitts@midsouth.rr.com webmaster - http://www.mschess.org
Stephen Pitts writes:
_.None should work: <dtml-var "_.None,_,password=new_password, ...)">
Ahh.. the mystical incantations. That seems to have done the trick, so I can both avoid copious let tags, and the 'infinite recursion' wierdness I was experiencing. Thanks. John.
John Morton writes:
Scenario:
So in my password change report I want to do something like this:
(name and new_password arrive from the request, pwd_format is an acquired default)
<dtml-call "sql_change_password( user_id=sql_get_user_id(name=name), password=encodePassword(password=new_password), pwd_format=pwd_format )">
Of course this won't work because user_id ends up being a list reference or something, so I tried this: <dtml-let name="'jwm'" old_password="'clear'" new_password="'foobar'"> <dtml-let password=new_password> <dtml-let enc_pass="encodePassword"> <dtml-in "sql_get_user_id(name=name)"> <dtml-call "sql_change_password(user_id=id,password=enc_pass,pwd_format=pwd_format)"> </dtml-in> </dtml-let> </dtml-let> </dtml-let> ...which also doesn't work, resulting in more complaints about infinite recursion. But this does: <dtml-let name="'jwm'" old_password="'clear'" new_password="'foobar'"> <dtml-let password=new_password> <dtml-let enc_pass="encodePassword"> <dtml-in "sql_get_user_id(name=name)"> <dtml-if enc_pass> <dtml-call "sql_change_password(user_id=id,password=enc_pass,pwd_format=pwd_format)"> </dtml-if> </dtml-in> </dtml-let> </dtml-let> </dtml-let> It looks like a side effect of the caching properties of <dtml-if ...> is that encodePassword gets evaluated at the 'if'. Of course, I expected it would get evaluated at the <dtml-let> tag, but it appears that in the first piece of code it gets evalutate in sql_change_password somehow, so that it's trying to get a value for password by calling encodePassword which needs a property called password, so it tries to get a value for password... Is that what's happening? Should it be? John.
participants (3)
-
John Morton -
Pavlos Christoforou -
Stephen Pitts