Hello, On Mon, Jan 22, 2007 at 05:03:43PM +0100, Alex Furlong wrote: > i have some problems with creating a custom edit form. Here is my complete > test code: > > from zope.formlib import form > from zope.publisher.browser import TestRequest > > class MyEdit(form.EditForm): > > def __init__(self, context, request): > self.context = context > self.request = request > > import pdb;pdb.set_trace() # set debugger break point > action = form.Action('Edit', success='handle_edit_action')
Ah, this is going to be fun :) > self.actions = form.Actions(action) > > def test(): > request = TestRequest() > obj = object() > > myform = MyEdit(obj, request) > > If i use this code in Zope then i get an error like this: "Action > object does not have an attribute 'form' ". *nod* > So my first question is, where does the 'form' attribute come from? Magic. Do you know how methods work in Python? You assign a function to a class attribute, and when you access that attribute on an instance of the class, you get back a bound method. The bound method knows which instance you used -- that's why it's called a bound method. Under the hood this is implemented using descriptors. A descriptor is an object that has a special __get__ method. When the value of a class attribute is a descriptor, and you access that attribute on an instance, the descriptor's __get__ gets called and return the value that you'll get. The __get__ of an unbound method will create a bound method object. Likewise, the formlib's form.Action class has a __get__ method that returns a copy of the action, with the 'form' attribute set. This mechanism only works when you assign descriptors to class attributes. It does not work when you assign descriptors to object attributes, or local variables, like you did. The simplest way to fix your problem is to bind the actions manually: def __init__(self, context, request): self.context = context self.request = request action = form.Action('Edit', success='handle_edit_action') action = action.__get__(self) self.actions = form.Actions(action) Or you can do it all in one go def __init__(self, context, request): self.context = context self.request = request action1 = form.Action('Edit', success='handle_edit_action') action2 = form.Action('Edit Again', success='handle_edit_action') actions = form.Actions(action1, action2) self.actions = form.Actions(actions).__get__(self) I do not know whether there are cleaner solutions. (I always feel a bit dirty when I call a method that starts with an underscore on an object other than 'self'.) HTH, Marius Gedminas -- TCP_UP - The 16-bit TCP Urgent Pointer, encoded as the hex representation of the value of the field. The hex string MUST be capitalized since it is urgent. -- RFC 3093
signature.asc
Description: Digital signature
_______________________________________________ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users