Pass objects from template to template via HTML forms.
Is there some way to pass an object from template A to template B via HTML forms? A <form name="a" action="b" method="post"> <input type="hidden" name="obj" tal:attributes="value here" /> <input type="submit" value="Press" /> </form> B <b tal:content="structure here/REQUEST"></b> Template B prints: form obj '<OrderedFolder instance at 42d9aec0>' I need the object itself, not the string representing the object! I already searched the archive and found a similar request (http://mail.zope.org/pipermail/zope/2003-November/143487.html), but I have not solved the problem. Can you suggest something to try? Thanks
On 04.Jul 2005 - 22:53:58, Negroup - wrote:
Is there some way to pass an object from template A to template B via HTML forms?
A <form name="a" action="b" method="post"> <input type="hidden" name="obj" tal:attributes="value here" /> <input type="submit" value="Press" /> </form>
B <b tal:content="structure here/REQUEST"></b>
Template B prints: form obj '<OrderedFolder instance at 42d9aec0>'
I need the object itself, not the string representing the object!
You do get the object itself when you access REQEUST['obj'], only in HTML you get something like the above, as that's what the string represenation of obj is. Andreas -- Try to relax and enjoy the crisis. -- Ashleigh Brilliant
2005/7/4, Andreas Pakulat <apaku@gmx.de>:
On 04.Jul 2005 - 22:53:58, Negroup - wrote: [cut]
<b tal:content="structure here/REQUEST"></b> [cut] You do get the object itself when you access REQEUST['obj'], only in HTML you get something like the above, as that's what the string represenation of obj is.
Why then, if template b is: <b tal:define="obj python:here.REQUEST['obj'].getId()"></b> (or <b tal:define="obj python:here.REQUEST.form['obj'].getId()"></b>) zope gives this error? Error Type: AttributeError Error Value: 'str' object has no attribute 'getId'
Negroup - wrote:
Why then, if template b is: <b tal:define="obj python:here.REQUEST['obj'].getId()"></b> (or <b tal:define="obj python:here.REQUEST.form['obj'].getId()"></b>)
zope gives this error?
Because REQUEST.form['obj'] is already a string representation of then object, not object itself, hence it has not method getId() Try looking into copy/cut/paste machinery, it seems to be what you're looking for
2005/7/5, Konstantin E. Steuck <phoenix_12@ngs.ru>:
Negroup - wrote: [cut] Try looking into copy/cut/paste machinery, it seems to be what you're looking for
This is a thing I absolutely want to avoid. I simply need to pass an object directly from one template to another, without intermediate steps (like, copying or creating the object with some manage_*method from a template, read the created object from the other template and then remove the object itself because unuseful..). In python it is so immediate: I pass objects between functions via parameters; in zope the most natural way to "simulate" parameters passing from one zpt and another is storing them inside the request object, and thus, using html forms. But for some reasons that I'm missing, it doesn't work!
Negroup - wrote:
This is a thing I absolutely want to avoid. I simply need to pass an object directly from one template to another, without intermediate steps (like, copying or creating the object with some manage_*method from a template, read the created object from the other template and then remove the object itself because unuseful..). Sure, you don't need to use copy/paste mechanism, just look on the implementation. AFAIR it just pickles list of absolute_url()'s and stores base64-encoded result into cookies.
Am Montag, den 04.07.2005, 22:53 +0200 schrieb Negroup -:
Is there some way to pass an object from template A to template B via HTML forms?
A <form name="a" action="b" method="post"> <input type="hidden" name="obj" tal:attributes="value here" /> <input type="submit" value="Press" /> </form>
B <b tal:content="structure here/REQUEST"></b>
Template B prints: form obj '<OrderedFolder instance at 42d9aec0>'
I need the object itself, not the string representing the object!
You cannot simply pass a ZOPE object in a form like that. You can handle fairly complex structures (lists and dictionaries with int, float, string in them) but whole objects would need to be pickled and then open a huge security hole (Whatever is in the client can and will be faked) So best option I see is to not pass the object but rather pass the reference to the object. You can resolve it via restrictedTraverse('/path/from/form') Btw. avoid much code in the Template. Its a maintenance headache. You can do it esily in a python script and call this from template.
2005/7/5, Tino Wildenhain <tino@wildenhain.de>: [cut]
So best option I see is to not pass the object but rather pass the reference to the object. You can resolve it via restrictedTraverse('/path/from/form')
I think I can't apply your solution. restrictedTraverse asks for a path, and then it supposes that the object is stored inside ZODB. This is not my case. Let me provide a minimanl explaination about how my application is structured. 1. A user can uploads a zipped file via HTML form in "upload_zip" ZPT. The action of the form points to check_zip, an External Method that checks for validity of each file inside the archive. 2. check_zip returns to upload_zip a tuple containing two elements: True or False (based on the correctness of archive) and the object itself, via self parameter. 3. after the external method has been called, upload_zip shows other 2 forms that the user will use to abort operation or to continue the process. The form to continue will pass the object to another external method in order to compute the result. This is the step where I encounter the problem, I can't pass object. This should explain why I haven't the object stored inside ZODB. Probably the solution would be to store the uploaded object inside a temporary area of ZODB and then I'll be able to do all the tasks I need. Any further consideration/hints? Thanks
Btw. avoid much code in the Template. Its a maintenance headache. You can do it esily in a python script and call this from template.
Yes, once found the way to follow, spread the code between dedicated objects will be pure amusement ;-)
+-------[ Negroup - ]---------------------- | 2005/7/5, Tino Wildenhain <tino@wildenhain.de>: | [cut] | | > So best option I see is to not pass the object but rather | > pass the reference to the object. You can resolve | > it via restrictedTraverse('/path/from/form') | | I think I can't apply your solution. restrictedTraverse asks for a | path, and then it supposes that the object is stored inside ZODB. This | is not my case. Let me provide a minimanl explaination about how my | application is structured. | | 1. A user can uploads a zipped file via HTML form in "upload_zip" ZPT. | The action of the form points to check_zip, an External Method that | checks for validity of each file inside the archive. | | 2. check_zip returns to upload_zip a tuple containing two elements: | True or False (based on the correctness of archive) and the object | itself, via self parameter. | | 3. after the external method has been called, upload_zip shows other 2 | forms that the user will use to abort operation or to continue the | process. The form to continue will pass the object to another external | method in order to compute the result. This is the step where I | encounter the problem, I can't pass object. | | This should explain why I haven't the object stored inside ZODB. | | Probably the solution would be to store the uploaded object inside a | temporary area of ZODB and then I'll be able to do all the tasks I | need. | | Any further consideration/hints? You would be better off storing the file on the filesystem, and pass the filename around. You'd have to do some sanity checking on the filename before any manipulation obviously. -- Andrew Milton akm@theinternet.com.au
Am Dienstag, den 05.07.2005, 11:05 +0200 schrieb Negroup -:
2005/7/5, Tino Wildenhain <tino@wildenhain.de>: [cut]
So best option I see is to not pass the object but rather pass the reference to the object. You can resolve it via restrictedTraverse('/path/from/form')
I think I can't apply your solution. restrictedTraverse asks for a path, and then it supposes that the object is stored inside ZODB. This is not my case. Let me provide a minimanl explaination about how my application is structured.
1. A user can uploads a zipped file via HTML form in "upload_zip" ZPT. The action of the form points to check_zip, an External Method that checks for validity of each file inside the archive.
2. check_zip returns to upload_zip a tuple containing two elements: True or False (based on the correctness of archive) and the object itself, via self parameter.
3. after the external method has been called, upload_zip shows other 2 forms that the user will use to abort operation or to continue the process. The form to continue will pass the object to another external method in order to compute the result. This is the step where I encounter the problem, I can't pass object.
This should explain why I haven't the object stored inside ZODB.
Probably the solution would be to store the uploaded object inside a temporary area of ZODB and then I'll be able to do all the tasks I need.
Any further consideration/hints?
Well yes, thats very easy. Just store your (compressed or not) HTML data (since its a string after all and not such a complex object) in a hidden form field (base64 encoded for example) -> filedata=htmldata.encode("base64") and the other parts of your form as you wish. Maybe you prepare the data in a script and call the ZPT from it: return context.yourZPT(filedata=filedata,somestatus=whatever) and use: <input type="hidden" tal:attributes="value options/filedata" type="text" /> in your ZPT. When the request returns, use: htmldata=filedata.decode("base64") alternatively you can just store the data in REQUEST.SESSION to keep it on server (but watch the memory usage) -- Tino Wildenhain <tino@wildenhain.de>
On Mon, 04 Jul 2005 22:53:58 +0200, Negroup - wrote:
Is there some way to pass an object from template A to template B via HTML forms?
A <form name="a" action="b" method="post"> <input type="hidden" name="obj" tal:attributes="value here" /> <input type="submit" value="Press" /> </form>
B <b tal:content="structure here/REQUEST"></b>
Template B prints: form obj '<OrderedFolder instance at 42d9aec0>'
I need the object itself, not the string representing the object!
No can do I'm afraid. The objects you deal with live only in the Zope server. When you send a response back to a user, this is just HTML, made of strings. Based on this, the user's browser sends back a new HTTP request, again made up of strings. When this new request arrives, Zope has forgotten the previous response, apart from perhaps something in a user's session or in the ZODB somewhere. So, if you wish to keep track of an object during a sequence of requests with the user, you must make arrangements to keep the object somewhere in Zope, and to find it as each request comes in. Common ways to cope in this situation include: - Make do without an object at all; run everything with just strings until you come to the end of the process and are ready to commit to the ZODB. - Store an object in the user's session. - Store an object in a temporary location in the ZODB, and pass around a path to it in your various forms. Hope this helps. Thanks, Malcolm. -- [] j a m k i t web solutions for charities malcolm cleaton T: 020 7549 0520 F: 020 7490 1152 M: 07986 563852 W: www.jamkit.com
2005/7/4, Negroup - <negroup@gmail.com>:
Is there some way to pass an object from template A to template B via HTML forms? [cut]
Thanks a lot for the replies. I have considered all the solutions and at the end I have decided to store the uploaded file in a zope file object inside ZODB, passing it between zope and external methods in order to process it, and then remove the file from ZODB. This is the last thing I wanted to do, but considering the traps I encountered storing objects inside the session (Error Type: TypeError, Error Value: can't pickle function objects), and considering also that the file uploaded by the user could be potentially very big in size, I have thougt that store it inside ZODB instead of a session object was a better solution. P.S. I just discovered a mail that looks like mine: http://mail.zope.org/pipermail/zope/2001-August/098793.html Probably in 4 years a lot of people have met the same "problem", but still there is no solution to face it in the terms expressed in my initial post; so, finally, is it impossible to implement a such thing or it simply has never been done?
Am Dienstag, den 05.07.2005, 16:47 +0200 schrieb Negroup -:
2005/7/4, Negroup - <negroup@gmail.com>:
Is there some way to pass an object from template A to template B via HTML forms? [cut]
Thanks a lot for the replies. I have considered all the solutions and at the end I have decided to store the uploaded file in a zope file object inside ZODB, passing it between zope and external methods in order to process it, and then remove the file from ZODB.
This is the last thing I wanted to do, but considering the traps I encountered storing objects inside the session (Error Type: TypeError, Error Value: can't pickle function objects), and considering also that the file uploaded by the user could be potentially very big in size, I have thougt that store it inside ZODB instead of a session object was a better solution.
P.S. I just discovered a mail that looks like mine: http://mail.zope.org/pipermail/zope/2001-August/098793.html Probably in 4 years a lot of people have met the same "problem", but still there is no solution to face it in the terms expressed in my initial post; so, finally, is it impossible to implement a such thing or it simply has never been done?
Well err. You have got all possible solutions: create object in ZODB and pass references around, create object in session (which is easy, you just store the string with the data) or send the data in the form between client and server. (Your error you mention above indicates you did not really create an object or used atomic datatypes) All methods have drawbacks and advantages. Despite of having the user select the same file again to send (which would be the 4th solution) there is none left. This isnt genuine to zope but inherent to all solutions which work over HTTP. I'd suggest to skip the 2-phase upload in favour of a one shot with all the relevant data. E.g. "[ ] check here if you want this and that" in the same form as the file gadget. Especially if the files are potentially large.
participants (6)
-
Andreas Pakulat -
Andrew Milton -
Konstantin E. Steuck -
Malcolm Cleaton -
Negroup - -
Tino Wildenhain