How to override a zope.formlib @form.action method in a ore.viewlet.core.FormViewlet
Summary:
- Plone 3.3.4
- Products.PloneGetPaid 0.8.8
- ore.viewlet 0.2.1
I am trying to override a viewlet class that inherits from ore.viewlet.core.FormViewlet. It has two methods decorated with @form.actio开发者_运维技巧n
(which is imported from zope.formlib). I need to override only one of them. If I don't define the other one, too, its action is unavailable. So I defined it, trying to simply pass the return value of the parent class. But then I get a TypeError: 'Action' object is not callable
.
Details:
Specifically, I'm overriding Products.PloneGetPaid.browser.cart.ShoppingCartActions, which is defined like this:
class ShoppingCartActions( FormViewlet ):
I defined the overriding class to inherit from this. The two decorated methods are:
@form.action(_("Continue Shopping"), name='continue-shopping')
def handle_continue_shopping( self, action, data ):
and
@form.action(_("Checkout"), condition="doesCartContainItems", name="Checkout")
def handle_checkout( self, action, data ):
I really only care about overriding the first. I'd like to leave the other one alone. These two @form.action methods generate the "Continue Shopping" and "Checkout" buttons in the "Next Steps" viewlet of the Shopping Cart Management page. If I only define the "Continue Shopping" method in my subclass, the "Checkout" button disappears. So I tried defining the Checkout method like this:
@form.action(_("Checkout"), condition="doesCartContainItems", name="Checkout")
def handle_checkout( self, action, data ):
return super( ShoppingCartActions, self ).handle_checkout(action, data)
But then I get this error:
2011-05-20 17:01:40 ERROR Zope.SiteErrorLog http://localhost:8080/obrien/@@getpaid-cartTraceback (innermost last):
Module ZPublisher.Publish, line 119, in publish
Module ZPublisher.mapply, line 88, in mapply
Module ZPublisher.Publish, line 42, in call_object
Module Products.PloneGetPaid.browser.cart, line 46, in __call__
Module zope.viewlet.manager, line 104, in update
Module ore.viewlet.core, line 15, in update
Module Products.PloneGetPaid._patch, line 44, in update
Module zope.formlib.form, line 750, in update
Module zope.formlib.form, line 594, in success
Module plonetheme.obrienskin.browser.cart, line 23, in handle_checkout
TypeError: 'Action' object is not callable
This makes me think that there must be some trick to overriding and inheriting methods decorated with @form.action
.
Any tip would be appreciated.
Thanks!
@form.action
wraps the method into an form.Action
instance and binds it there to the success_handler
attribute. So your code should look like this:
@form.action(_("Checkout"), condition="doesCartContainItems", name="Checkout")
def handle_checkout( self, action, data ):
return super(ShoppingCartActions, self).handle_checkout.success_handler(
self, action, data)
maybe it is more a problem with super than with decorate
One big problem with 'super' is that it sounds like it will cause the superclass's copy of the method to be called. This is simply not the case, it causes the next method in the MRO to be called.
That misconception causes people to make two common mistakes.
- People omit calls to super(...).init if the only superclass is 'object', as, after all, object.init doesn't do anything! However, this is very incorrect. Doing so will cause other classes' init methods to not be called.
- People think they know what arguments their method will get, and what arguments they should pass along to super. This is also incorrect.
http://fuhm.net/super-harmful/
Personnaly I didn't have any problem to override for example @form.action(_("Update"), condition="isNotEmpty") in ShoppingCartAddItem I am not an expert and these modifications are quite old ... I just made my changes leaving alone the remaining code without using super ...if you know what I want to mean...
精彩评论