[ZPatterns] _v_dm_ KeyError calling get_transaction().abort()

Phillip J. Eby pje@telecommunity.com
Mon, 08 Oct 2001 19:58:33 -0500


At 09:33 AM 10/9/01 +1000, Itai Tavor wrote:

>Not quite sure what you mean by "get your self object again" - do you mean 
>do self=self.getItem(self.id)? This trickery is a bit over my head...

Just to explain more clearly what's going on, I thought I'd jump in for a 
second...

ZPatterns objects retrieved from a Rack are not guaranteed to remain valid 
across transactional boundaries.  In particular, aborting a transaction 
(even a subtransaction) guarantees that any references you have to a 
DataSkin will be invalid.  You *must* re-retrieve the object from the Rack, 
or, in the case of a non-rackmounted DataSkin, re-retrieve it from its 
container.  My suggestion for the code would be something like:

id, DM = self.id, self._v_dm
get_transaction().abort()
self = DM.getItem(id)

Thus, self is now a reference to an object in the *new* transaction 
space.  It will have all its "magic" properly in place, where the aborted 
object will not.

Please note that if any other references to DataSkins which were saved 
before the aborted transaction are used, they will also be invalid and 
cause errors.

Technically speaking, references should not be held even across a 
subtransaction commit operation, but this doesn't usually cause many 
problems in practice.  The only potential issue with a commit is that the 
Rack's per-transaction cache will be cleared, so when using virtual (e.g. 
SQL) objects, a post-commit retrieve might return an object which is not 
the "same" object as the one you hold a reference to.  This is only a 
problem if you do such a thing, of course.


>Could you please describe how you would solve this problem? I'd really 
>like to know if there is a better approach.
>
>Just to make sure you understood my problem correctly: The edit method 
>modifies the object, and possibly modifies and creates other related 
>objects, with values submitted in a form. If any of these actions cause 
>errors, these are added to an 'errors' dictionary. I then roll back all 
>the changes and display the errors by rendering the original form. The 
>need to abort came from the fact that the form is rendered while the 
>object is in its new, invalid state, because the changes have not been 
>rolled back yet.

Hm.  My usual approach to handling this is to just throw an error when a 
problem is found, albeit a fancy error text explaining the problem, and ask 
the user to press the back button to go back and correct.

However, I think the simple way to do what you want is probably just to 
pre-render the form *before* you do the operations which might cause 
errors.  If you get an error, just raise the pre-rendered form.  Of course, 
it's more complex if you embed the error text multiple places in the form...