Hello. Something came up today that I'm not sure how to deal with. A long and wordy explanation follows, but the quick question I have is this: without using sessions, or anything else tied into transactions / persistence but tied to the current visitor, how can I write to a very small 'messenger' store to send messages like "Item Deleted" or "3 Items Added to Cart" that, when read back from, removes those message. I just tried a cookie based implementation, but since the request and response track cookies differently, I can't selectively write and retrieve/clear these messages as easily as I'd like. The important thing about these messages is that (a) the user sees them only once, and (b) they can survive redirects. I've done this using a session based utility that I wrote a long time ago, but the session based one has some problems with a new feature I'm trying (interfering with "undo last") and I'm not sure that doing so much frequent writing / clearing to a ZODB storage is such a good thing.
I don't know if having event listeners pull data out of cookies and putting them into a threading.local type container is a good way to go, writing anything new and expiring anything old when the response is written out - and in-request I just read and write from that little transient thing. Or can a _v_attribute (don't know where it'd attach) or request annotation work? I still don't understand the life cycles of some of these options, nor how to ensure they don't interfere with other transactions so that "Undo Last" doesn't undo the removing of the notification message and nothing else. -- LONG VERSION -- I've been using a session based Page Messenger for a while now. I wrote about it a couple of years ago [1]. The use case is for displaying messages to the user in a uniform way - not tacking them onto a query string, not stuffing them into the current view or request, but putting them somewhere that can survive the current request so that redirects can still show the message. [1] http://euc.cx/toulouse/archives/2003/12/22/page_messages.html I've loved this pattern, and I've just used Zope's sessioning support (for better or worse) to deal with it, and it's generally worked out great. In Zope 2 I put it behind a CMF Tool-like interface and turned it into a utility for our Zope 3 apps. Ruby on Rails calls it 'flash', and Subway and TurboGears both sport this flash feature, often just using cookies. The pattern is basically this: add a message to the messenger, it stores it ... somewhere, anywhere. Later, in the same request or perhaps the next, the messages are retrieved (my implementation's always allowed for multiple messages). When they are retrieved, they're removed from the storage so the user sees the message only once (ie - reloading the page won't bring back the "Deleted Item 'x'" message). Today I was working on having 'undo' messages, similar to those im GMail. I was frustrated trying to put a javascript confirm on a browserMenuItem ('delete'), when I remembered that Zope has this great undoable database. So I borrowed code from zope.app.undo.browser to just do the 'undo last', and returned a message that had a link to the @@undolast view. So a user can visit an object directly and see a 'Delete' action. When they delete, they go back to a content listing and now get the message "Deleted 'Foo Title' [foo id] (Undo)". But since my page messenger uses sessions - the 'undo last action' would only undo the removal of the **undo message** from the messenger container in the session. This is because the page is a redirect, and at the time of clicking "undo last", the last action is the page view that retrieved the notification message and removed it from the notification store. I've long wanted to try some alternate page messenger implementations anyways, and went about doing a cookie based one. I've got it working - including handling multiple messages of different styles (info, error, warning, etc)... to a point. It works great on a redirect, but not within the same request. Which is obvious to me now - I'm only looking at cookies in the Request, not the Response. Likewise, items aren't cleared from the Request until the end of the response (whereas sessions would go immediately). Is there a better pattern I could be using here, where cookies are kindof the fallback? I guess I'd like to safely: * Load all of the current messages stored in cookies at the beginning of request handling and put them in a container that exists only for the duration of the request. * Access that container throughout the current request to get messages for display and set new ones for display on the next page view, whether it's from a call later in that request (return self.template...) or after a redirect. * Write undisplayed messages out to cookies at the end of the request (again, whether it was a redirect or full page view). Of course, no visitor should see any other visitors messages. This is why sessions worked nicely - I didn't really have to think about it. But I may have been using them poorly by doing so much writing just to display a message to a user. Can I listen to events to catch the beginning of the request, before traversal, and get all of these message cookies out of the request and into something like a 'thread.local' based object? I don't understand threads and requests all that well, I must admit, so I don't know if that's applicable. Then, my utility does all of its interaction with that 'local' storage that is not transactional or ZODB based: just something holding a handful (typically one) message to display to the current site visitor. At the end of the request cycle, before the response is sent, another event listener sets or expires cookies based on whats in that container. Is that possible? _______________________________________________ Zope3-users mailing list [email protected] http://mail.zope.org/mailman/listinfo/zope3-users
