[Zope3-Users] formlib with no zodb
Maciej Wisniowski
maciej.wisniowski at coig.katowice.pl
Fri Mar 16 05:36:48 EDT 2007
> Is it possible to build a page with formlib, widgets, and a page
> template without using the ZODB or ZMI. I have been trying for awhile
> to accomplish this with no luck. I want to build an edit form that
> shows results from a postgresql database which does not add any
> objects within the zodb. If anyone can help or has any examples I
> would really appreciate it.
Recently I started to write real application that uses my
product for RDBMS interaction (I've sent you links to
very first (and very unstable) version of this).
Because of doing real work I did some fixes and changes to
my general product. I called this 'dbformlib'. First stable version
is available at:
http://dbcrudbase.googlecode.com/svn/tags/dbformlib_1_0/
I know that you may hate this product already because of it's
recent unstability (but it was still developement)
but if you want to give it second try then take a look at it now.
In general it is supposed to create one content object
that is a gateway between user and RDBMS. Each content object
handles one(!) form (but a lot of rows from database).
Eg. you have table Account in RDBMS
so you will create 'account_content object' that will have
few SQLScripts inside to call: select, update, insert, delete
statements on Account table.
Then you will create views for edit, add, delete (just like in formlib).
Only difference is that for forms other than 'add' you need row id
to know which row should be returned from database.
row 'id' is called Entry parameter by me, because it has to
appear in request like:
http://localhost/mysite/mycontentobj/edit.html?in.id=1
thanks to this, your's select can be like:
select * from Account where id=<dtml-sqlvar id type="int">
Simple usage may be seen at application located at:
docs/sample but this doesn't use real database.
Description is at docs/sample/Readme.txt.
Below some code from my real app that uses dbformlib.
One important thing is connectionName. You have to
create (and register at your site) database adapter.
It's name is then used as 'connectionName'.
In my case I have site that during add, creates my content
and sets connectionName but you may use hardcoded value
instead of self.Connection while creating SQLScripts.
For a start you may take 'Sample DBFormlib' application and create
some SQLMethods in it and just call them with hardcoded
'connectionname'.
interfaces.py
-----------------------
from zope.schema import TextLine, URI
from dbformlib.fields import EntryField
from dbformlib.interfaces import IDBFormlibContent
class IAccount(IDBFormlibContent):
""" Content object interface
"""
id = EntryField(title=u"id")
cancel_url = EntryField(title=u"cancel_url", required=False)
aplikacja = TextLine(title=u"Aplikacja")
adres = URI(title=u"Adres")
mycontent.py
-----------------------
from dbformlib.dbformlib import DBFormlibContent
from interfaces import IAccount
class Account(DBFormlibContent):
zope.interface.implements(IMonitorConfDB)
def setup(self):
# select
sql = 'select * from monitor_conf where id=<dtml-sqlvar id
type="int">'
sqlArguments = 'id'
sqlQuery = SQLScript(self.connectionName, sql, sqlArguments)
self['get_config_entry'] = sqlQuery
notify(ObjectCreatedEvent(sqlQuery))
# update
sql ='''update monitor_conf set
aplikacja=<dtml-sqlvar aplikacja
type="string">,
adres=<dtml-sqlvar adres type="string">
where id=<dtml-sqlvar id type="int">'''
sqlArguments = 'id aplikacja adres'
sqlQuery = SQLScript(self.connectionName, sql, sqlArguments)
self['set_config_entry'] = sqlQuery
notify(ObjectCreatedEvent(sqlQuery))
def _get_form_data(self, crud_id, in_params={}):
ret_dict={}
if crud_id=='edit':
try:
res = self['get_config_entry'](id=in_params['id'])
if res:
ret_dict['aplikacja']=res[0].APLIKACJA
ret_dict['adres']=res[0].ADRES
return ret_dict
raise UserError('No data for this ID!')
except DatabaseException, err:
raise UserError(u'DB error')
else:
return {'adres':'http://'}
def _set_form_data(self, crud_id, data, errors=[]):
try:
if crud_id=='edit':
self['set_config_entry'](id=data['id'],
aplikacja=data['aplikacja'],
adres=data['adres'])
except DatabaseException, err:
errors.append(u'db error...')
views.py
---------------
from zope.formlib import form
from zope.app.form.browser import BytesWidget
from zope.traversing.browser.absoluteurl import absoluteURL
from dbformlib.browser import DBFormlibEditForm
from monitor.interfaces import IAccount
class WideBytesWidget(BytesWidget):
displayWidth = 80
class AccountEditForm(DBFormlibEditForm):
label = u'Edit my data'
actions = DBFormlibEditForm.actions
def define_fields(self):
self.form_fields = form.Fields(IAccount)
self.form_fields['adres'].custom_widget = WideBytesWidget
@form.action(u'Cancel', validator=lambda *a: ()) # hack to omit
validation
def handle_cancel_action(self, action, data):
data = self.get_data_obj().get_data()
absoluteURL(self.context, self.request)
if data['cancel_url']:
self.request.response.redirect(data['cancel_url'])
return None
configure.zcml
-------------------------
...
<browser:page
name="edit.html"
for="..interfaces.IAccount"
class=".views.AccountEditForm"
permission="zope.View"
/>
...
--
Maciej Wisniowski
More information about the Zope3-users
mailing list