On 2/21/06, David Johnson <[EMAIL PROTECTED]> wrote: > Thanks. I will look into formlib. My goals is to be able to provide forms > that allow editing of SQL based database entries. I am exploring SQL and > Zope integration, and I liked the simplicity of the browser:form concept.
You'll (most likely) want zope.formlib then. It will give you the control you'll need while still providing a lot of useful base classes and helpful functions to keep form generation and validation simple. I had started writing my thoughts and past experiences with Zope - SQL integration here, but am moving that to a separate topic. > Here is what I am generally trying to do. Imagine a database of contacts. > My thought is to architect it as follows. > 1. Create a view which simply lists all the contacts. Each contact displayed > would be an href link to the individual contact. > 2. Clicking on a contact which generate a form to edit that contact. > > The href link for the contact would contain the contact id. > http://localhost/mycontacts/contact.html?contactid=1234 > > The __init__ of the browser:form I was planning to use to get the > "contactid" from the request. With formlib, you'd be able to get/set this in the update() method, or if you're clever, you can do it in publishTraverse so you can have url like '.../mycontacts/contact/1234'. If you're doing really custom data handling - ie, the data's not an object that a field can bind to but a dictionary - you'll probably want to use formlib.FormBase and override setUpWidgets and update() both. I'll show the publishTraverse trick that I've started to use too. This *should* work. Note: ``IContactGateway`` is a complete fabrication of my imagination. In this scenario, it loads and stores contact information from a SQL Database, returning a dictionary (load) and accepting a primary key and dictionary of validated / restricted data (only elements from the IContact interface in this case) to save. from zope.app import zapi from zope.formlib import form from myapp.interfaces import IContact, IContactGateway class ContactEditForm(form.FormBase): form_fields = form.FormFields(IContact) contactid = '' def publishTraverse(self, request, name): """ Used by zope.publisher to traverse to 'name' """ # We expect 'name' to be a contactid. Set it as the attribute. Return # self to the publisher, which will call __call__ (which then calls # self.update() and returns self.render()). self.contactid = name return self def setUpWidgets(self, ignore_request=False): """ Overrides FormBase.setUpWidget to send ``self.contact_data`` to the ``data`` argument of form.setUpWidgets. """ self.adapters = {} self.widgets = form.setUpWidgets( self.form_fields, self.prefix, request=self.request, form=self, adapters=self.adapters, ignore_request=ignore_request, data=self.contact_data ) def update(self): # How you load the contact record is up to you... contacts = self.contacts = zapi.getUtility(IContactGateway) self.contact_data = contacts.get(self.contactid) # FormBase.update calls self.setUpWidgets and responds to any # submitted action. super(ContactEditForm, self).update() # Here's where you can respond to 'save'. This creates a 'Save Contact' # button and calls the following method if form validation succeeds. @form.action(u'Save Contact') def handleSaveContact(self, action, data): # 'data' is the validated dictionary. How you save it is up to you # :-) self.contacts.save(self.contactid, data) self.status = "Changes Saved" In *theory*, that should set you up. The generated form's action will be a full URL which should include the contactid, so 'publishTraverse' will get called again with that contact id. (ie - it will render ``form action=".../contacts/1234"``, with 'contacts' being the name of this view). Alternately, in 'update', you could do:: self.contactid = self.request.get('contactid') But you would have to ensure that contactid is included in the rendered form. > I would use sqlos, but my limited exposure makes me think it is not as > flexible as I would like. I haven't used sqlos. A benefit of sqlos is that, in theory, it would load your Contact object and make it appear pretty much like any other Zope object. At that point you could use more regular forms. That would be a good thing. However, I personally feel there are other options that could be explored.. They may not exist yet :), but I've got thoughts brewing. -- Jeff Shell _______________________________________________ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users