I have taken a little bit of time to look at Martijn Faassen's ZFormulator product, and here are some findings: ZFormulator is a product that allows you to create self-validating HTML forms without hand-coding HTML form element constructs in DTML methods/documents. It allows you to use the Zope UI to set validation constraints on form input, to resize form elements, etc. Your role after creating the ZFormulator object in constructing a basic form is limited to calling the ZFormulatorForm object within DTML to get all the form elements, and setting a target action method for the form. - Martijn includes a .zexp file for demo purposes in the product which gets placed into the import directory upon untarring the product file. I think this is OK, but I wonder if anybody else has thoughts on the implications of placing stuff into directories other than the intended product directory within a product tarball? For instance, I would consider it bad form for a Product to expand something into the lib/python/OFS directory. Others might disagree. What about products just going right ahead and creating instances of their classes within the ZODB upon installation? Or products automatically importing demo .zexp (or equivalent) files into the App object? Bad form or no? - The owner and group of all Martij's product files are martijn/martijn. We had some talk lately about how untarring Products into the directory tree might lead to the unintended resetting of permissions. When I untarred the product, all the files were reset to owner/group mcdonc/mcdonc (my user login). I do not know under what circumstances tar creates files which have their permissions set to their build filesystem's permissions, or whether this is a behavior endemic to non GNUtar tar variants or what. I seemed to have no problem with gunzip ZFormulator.tgz, tar xvf ZFormulator.tar within the Zope homedir. Does anybody have any tips as to when tar decides to write files out with their original owner/group bits set instead of owner/group set to the untarring user? (yes, I am way too lazy to try to decode the WORST man page in history, the GNUtar manpage). - ZFormulator is a good example of how to create a folderish object within a Python product that constrains addable meta-types to certain other object types. In Martijn's product, he creates a base class named Form that inherits from ObjectManager, RoleManager, and SimpleItem. Since the Form base class inherits from ObjectManager, it is folderish. He overrides ObjectManager's all_meta_types method, and though I can't quite follow the logic as to how he populates the meta_types list within the class, it works, constraining the addable meta_types to those he chooses in a registration function (in this case, the individual field types, such as checkbox, textarea, etc.) I learned some tricks from this. One of the unintuitive things about constraining addable objects this way is that a ZFormulatorForm instance's Security tab still shows permission descriptions for aquired object types (such as Folders, etc). Not a really big deal, but sure to confuse some people. - The UI of ZFormulator is pretty standard, first you create a ZFormulatorForm object (this is an object that is represented by the Form class) by choosing it from the addable object dropdown. Then you click on that object to start messing with it. While you're messing around with it, you can add BasicFields, TextboxFields, CheckboxFields, and a bunch of other form widgets inside the Form. Each object type has its own icon (nice!) and each object type corresponds to a different object class (e.g. the TextareaField class, the CheckboxField class, etc.) You create the form widget object through the standard Zope management interface through the add dropdown. After you've done that, you navigate to the form object by clicking on it and redefining its properties. One thing that I'm sort of on the fence about is calling MessageDialog when properties for objects are changed. Martijn does this for most all changes within the UI. I sometimes find that this gets old after a while ("Yes, I know, thanks, I changed the object properties.") There isn't really much of a standard within Zope about calling MessageDialog (for example, SQL method Edit properties, when changed, don't call MessageDialog, they instead put a "last changed" blurb at the top of the management screen). Any comments? Additionally, what if a person were to create a Wizard-style interface for the addition of forms and form elements. Martijn has taken the approach of creating forms and form elements one-at-a-time via the Zope UI, but I could easily see a multipart form Wizard that would lead a user through the creation of a form and its elements without him or her knowing that he/she is instantiating things within the ZODB. Thoughts? - Martijn defines something like 27 classes that live within his product. Each of these classes, for the most part, is defined in a separate Python module within the product directory. I don't mind this at all. Anybody have anything to say about that? - I don't really want to get too deep into reviewing code here, so I'm just going to report errors and things that I think are a tiny bit askew (:-))... within a ZFormulator form, when adding a *second* instance of the same type of object (for example, a second TextareaField), I intermittently got an AttributeError, "None" object has no attributes coming from Field.py line 138 in _setSheet. Martijn, I would also give a little blurb as to what "Order" means within the Form elements add and edit UI as its not immediately obvious (I figured it out by reading the code). The View button between form elements produces inconsistent results (for example, a checkbox returns quoted HTML of the form element, while a textarea View shows the default value for the form element without any HTML). Also, the ListField input box for the list elements should probably be split into separate key/value fields instead of using the pipe as a separator between key and value within a textarea. I know SQL integration is a "work in progress", and doesn't actually do much yet. I'd almost be apt to leave it out of the product entirely as it's sort of hurts my brain to think about where my form values are coming from and going to in the context of using the product as a SQL conduit. Also, when navigating with the back-forward buttons within a browser between forms created using ZFormulator (even within the ZFormulator UI which "eats its own dogfood"), browser errors indicating that form responses have expired are common. I imagine this is a pretty tough one to avoid, and I haven't looked at the code closely enough to see why it happens with ZFormulator forms more often than with Zope HTMLFile-derived forms. Nice product Martijn! Well done! -- Chris McDonough Digital Creations, Inc. Zope - http://www.zope.org
[Chris McDonough, on Sat, 08 Jan 2000] :: - The owner and group of all Martij's product files are :: martijn/martijn. We had some talk lately about how untarring Products :: into the directory tree might lead to the unintended resetting of :: permissions. When I untarred the product, all the files were reset to :: owner/group mcdonc/mcdonc (my user login). I do not know under what :: circumstances tar creates files which have their permissions set to :: their build filesystem's permissions, or whether this is a behavior :: endemic to non GNUtar tar variants or what. I seemed to have no problem :: with gunzip ZFormulator.tgz, tar xvf ZFormulator.tar within the Zope :: homedir. Does anybody have any tips as to when tar decides to write :: files out with their original owner/group bits set instead of :: owner/group set to the untarring user? (yes, I am way too lazy to try :: to decode the WORST man page in history, the GNUtar manpage). You're right; the manpage is hairy. But tar itself is simple. It's probably helpful to remember that tar is, historically, a tape archiver (validated by the fact that if you don't specify the 'f filename' option, tar will assume you want to write to the first tape device). Most tape backups will be performed by root. tar preserves the original owner if you extract as root; otherwise, files will be owned by user (you). In either case, permissions, full directory structure, and symbolic/hard links, are retained.
Thanks. Understood. This is a pretty good argument against installing Zope itself as the root user. Patrick Phalen wrote:
You're right; the manpage is hairy. But tar itself is simple.
It's probably helpful to remember that tar is, historically, a tape archiver (validated by the fact that if you don't specify the 'f filename' option, tar will assume you want to write to the first tape device). Most tape backups will be performed by root.
tar preserves the original owner if you extract as root; otherwise, files will be owned by user (you). In either case, permissions, full directory structure, and symbolic/hard links, are retained.
-- Chris McDonough Digital Creations, Inc. Zope - http://www.zope.org
[Chris McDonough, on Sat, 08 Jan 2000] :: Thanks. Understood. :: :: This is a pretty good argument against installing Zope itself as the :: root user. Well, er, ahem, hmmm ... While I know what you mean by 'install', here, it might be worth clarifying, to prevent the spread of confusion ... This is a good argument against *untarring* Zope as root. Instead, su to nobody (or your version of nobody). Otherwise, Zope will likely be owned by one of the Pelletier clan. OTOH, Zope should be *installed* as root *if* you're intending to run ZServer behind another web server, right?
On Sat, 8 Jan 2000, Chris McDonough wrote:
- Martijn includes a .zexp file for demo purposes in the product which gets placed into the import directory upon untarring the product file. I think this is OK, but I wonder if anybody else has thoughts on the implications of placing stuff into directories other than the intended product directory within a product tarball? For instance, I would consider it bad form for a Product to expand something into the lib/python/OFS directory. Others might disagree. What about products just going right ahead and creating instances of their classes within the ZODB upon installation? Or products automatically importing demo .zexp (or equivalent) files into the App object? Bad form or no?
Apart from /Products and /Extensions (for external methods) and /usr/lib/Products (for python code), you will occasionally need a .zexp file to complete installation. For example, a product that is a mixture of ZClasses and External methods would probably be packed up in a tarball that puts the external methods in the correct place, and places a .zexp file in your import directory to create the ZClasses. -- ___ // Zen (alias Stuart Bishop) Work: zen@cs.rmit.edu.au // E N Senior Systems Alchemist Play: zen@shangri-la.dropbear.id.au //__ Computer Science, RMIT WWW: http://www.cs.rmit.edu.au/~zen
Chris McDonough wrote: [snip summary of what ZFormulator indeed does]
- Martijn includes a .zexp file for demo purposes in the product which gets placed into the import directory upon untarring the product file.
Yes, with XMLWidgets I had the .zexp separated out (one for demos and one for necessary ZClasses). Then I noticed some other products had the .zexp included and I like that better, as it's far less of a hassle to download and install. The components are heavily dependent on each other anyway; it's often unlikely for instance that a 0.1 demo runs with a 0.2 product.
I think this is OK, but I wonder if anybody else has thoughts on the implications of placing stuff into directories other than the intended product directory within a product tarball? For instance, I would consider it bad form for a Product to expand something into the lib/python/OFS directory.
Me too, if it didn't give appropriate warning.
Others might disagree. What about products just going right ahead and creating instances of their classes within the ZODB upon installation?
Can this actually be done?
Or products automatically importing demo .zexp (or equivalent) files into the App object? Bad form or no?
I think some installation framework could be created that allows things like this, but then the installation framework would need to explicitly state what is happening at each time. If you work with tarballs, the download page should state clearly that something tricky will happen, whenever something tricky happens. The import and extensions directories are okay in this way to me though, except that you could run into namespace problems. Some filenames could already be in use.
- The owner and group of all Martij's product files are martijn/martijn.
faassen/faassen, I'd think. :) [snip discussion of tar behavior, which has some good posts in this thread]
- ZFormulator is a good example of how to create a folderish object within a Python product that constrains addable meta-types to certain other object types.
Well, not too good as it's still buggy!
In Martijn's product, he creates a base class named Form that inherits from ObjectManager, RoleManager, and SimpleItem. Since the Form base class inherits from ObjectManager, it is folderish. He overrides ObjectManager's all_meta_types method, and though I can't quite follow the logic as to how he populates the meta_types list within the class, it works, constraining the addable meta_types to those he chooses in a registration function (in this case, the individual field types, such as checkbox, textarea, etc.)
The tricky part is that meta_types is officially a tuple. It can't be a list, to my great regret. This means I need to do some tuple adding in the register function, and then *manually* add change the *class* data member. Since the class is not used to create new fields before registration of fields happens, this works. It's not nice though. The Form.py file is full of hacks, just to make the registration process work cleanly. And it contains bugs; somehow you can't add a field if you aren't a superuser. I still would like to know what causes this. I'm completely in the dark myself. May be something obvious, but I don't know where to begin looking..
I learned some tricks from this. One of the unintuitive things about constraining addable objects this way is that a ZFormulatorForm instance's Security tab still shows permission descriptions for aquired object types (such as Folders, etc). Not a really big deal, but sure to confuse some people.
Would it be possible to actually get rid of the superfluous permission descriptions? I don't see currently how a product could tell Zope about this.. Couldn't/Shouldn't Zope check the meta_types itself for this?
- The UI of ZFormulator is pretty standard, first you create a ZFormulatorForm object (this is an object that is represented by the Form class) by choosing it from the addable object dropdown.
This works through semi-standard Zope object add code.
Then you click on that object to start messing with it. While you're messing around with it, you can add BasicFields, TextboxFields, CheckboxFields, and a bunch of other form widgets inside the Form. Each object type has its own icon (nice!) and each object type corresponds to a different object class (e.g. the TextareaField class, the CheckboxField class, etc.) You create the form widget object through the standard Zope management interface through the add dropdown.
Read: this works through horribly unstandard kludged up object add code. I keep wishing someone will look at it and propose a simple solution! And there's my bug..
After you've done that, you navigate to the form object by clicking on it and redefining its properties. One thing that I'm sort of on the fence about is calling MessageDialog when properties for objects are changed. Martijn does this for most all changes within the UI. I sometimes find that this gets old after a while ("Yes, I know, thanks, I changed the object properties.")
Me too, but it was in the code I copied and when I tried to change it into the way DTML methods are edited, it didn't work anymore. :) I didn't dig into this, though.
There isn't really much of a standard within Zope about calling MessageDialog (for example, SQL method Edit properties, when changed, don't call MessageDialog, they instead put a "last changed" blurb at the top of the management screen). Any comments?
I generally like the 'last changed' blurb better. This is a typical area for product GUI guidelines.
Additionally, what if a person were to create a Wizard-style interface for the addition of forms and form elements. Martijn has taken the approach of creating forms and form elements one-at-a-time via the Zope UI, but I could easily see a multipart form Wizard that would lead a user through the creation of a form and its elements without him or her knowing that he/she is instantiating things within the ZODB. Thoughts?
I think you could make a separate wizard system that calls ZFormulatorForm when necessary through some unspecified-as-yet API. I think a wizard has rather a lot of limitations though, as you will make mistakes and you'll want to adjust things later. So you'd go into the ZFormulator interface again after all. ZFormulator is not aimed at content managers primarily (though it may help here) but at developers.
- Martijn defines something like 27 classes that live within his product. Each of these classes, for the most part, is defined in a separate Python module within the product directory. I don't mind this at all. Anybody have anything to say about that?
ZFormulator defines a system which allows you to 'plug in' your own field classes. That's why I put most of the classes in separate files.
- I don't really want to get too deep into reviewing code here,
darn. :)
so I'm just going to report errors and things that I think are a tiny bit askew (:-))... within a ZFormulator form, when adding a *second* instance of the same type of object (for example, a second TextareaField), I intermittently got an AttributeError, "None" object has no attributes coming from Field.py line 138 in _setSheet.
Hm. Perhaps this is a bug I already fixed, but I can't reproduce this one right now.
Martijn, I would also give a little blurb as to what "Order" means within the Form elements add and edit UI as its not immediately obvious (I figured it out by reading the code).
All right. ZFormulator needs more documentation anyway. :)
The View button between form elements produces inconsistent results (for example, a checkbox returns quoted HTML of the form element, while a textarea View shows the default value for the form element without any HTML)
The HTML *is* being spewed (look at the page source), but since it's just a fragment so it's just randomly misinterpreted by the browser. The entire 'view' feature is dubious with the 'test' tab already there anyway, so I may just remove it. Anyone have any opinions?
Also, the ListField input box for the list elements should probably be split into separate key/value fields instead of using the pipe as a separator between key and value within a textarea.
Which leads to beautiful problems with two seperately scrollable textarea widgets? :) I'm interested in offering 'complex widgets' for ZFormulator eventually, i.e. widgets consisting of more than a single HTML form element, with extra buttons for some functionality, etc. Still thinking about this one.
I know SQL integration is a "work in progress", and doesn't actually do much yet. I'd almost be apt to leave it out of the product entirely as it's sort of hurts my brain to think about where my form values are coming from and going to in the context of using the product as a SQL conduit.
SQL integration does need some rethink. Some people have been thinking about it more than I have recently, and eventually I hope to progress some on this front. I'm not sure I understand your brain-hurt, though. My brain-hurt is different and has to do with table synchronisation issues (if you change the form, the SQL table structure can change, so what now?).
Also, when navigating with the back-forward buttons within a browser between forms created using ZFormulator (even within the ZFormulator UI which "eats its own dogfood"), browser errors indicating that form responses have expired are common. I imagine this is a pretty tough one to avoid, and I haven't looked at the code closely enough to see why it happens with ZFormulator forms more often than with Zope HTMLFile-derived forms.
Hm, I don't know a thing about form responses expiring and such. I'll need to think more about this one.
Nice product Martijn! Well done!
Thanks! Any clues on cleaning up Form.py and getting rid of my bug? :) Regards, Martijn
Chris McDonough wrote: [snip]
One thing that I'm sort of on the fence about is calling MessageDialog when properties for objects are changed.
I'll dig through the source for DTML Method to find out what it does there, and I'll try using that instead. [snip]
- I don't really want to get too deep into reviewing code here, so I'm just going to report errors and things that I think are a tiny bit askew (:-))... within a ZFormulator form, when adding a *second* instance of the same type of object (for example, a second TextareaField), I intermittently got an AttributeError, "None" object has no attributes coming from Field.py line 138 in _setSheet.
Okay, I haven't been able to reproduce this one yet. If anyone encounters this, please report it to me. Perhaps I 'accidentally' fixed it in the to-be-released-today ZFormulator 0.2?
Martijn, I would also give a little blurb as to what "Order" means within the Form elements add and edit UI as its not immediately obvious (I figured it out by reading the code).
Okay, I put a blurb on top of the edit screen explaining 'order' and 'title' (both are common to all fields).
The View button between form elements produces inconsistent results (for example, a checkbox returns quoted HTML of the form element, while a textarea View shows the default value for the form element without any HTML).
I've taken the 'view' tab out; the 'test' tab should be sufficient. If anyone complains I'll listen. :)
Also, the ListField input box for the list elements should probably be split into separate key/value fields instead of using the pipe as a separator between key and value within a textarea.
I'll probably continue to use the pipe for now.
I know SQL integration is a "work in progress", and doesn't actually do much yet. I'd almost be apt to leave it out of the product entirely as it's sort of hurts my brain to think about where my form values are coming from and going to in the context of using the product as a SQL conduit.
I'm leaving it in for now, unchanged; Ross Lazarus is working on more SQL integration for ZFormulator and I'm waiting for his feedback before I tackle SQL integration again myself. We've been doing some thinking about this.
Also, when navigating with the back-forward buttons within a browser between forms created using ZFormulator (even within the ZFormulator UI which "eats its own dogfood"), browser errors indicating that form responses have expired are common. I imagine this is a pretty tough one to avoid, and I haven't looked at the code closely enough to see why it happens with ZFormulator forms more often than with Zope HTMLFile-derived forms.
Which browser do you use? These browser errors are very rare for me with Netscape 4.7 on Linux. When using Internet Explorer 5 though I've noticed this kind of error quite a bit in Zope. Anyone know more about this issue? Regards, Martijn
participants (4)
-
Chris McDonough -
Martijn Faassen -
Patrick Phalen -
Stuart 'Zen' Bishop