[Zope3-Users] Re: URL Traversal/SelectedManagementView
Jeff Rush
jeff at taupro.com
Tue Jan 17 06:41:55 EST 2006
David Johnson wrote:
>
> I want to create an instance of a class that does not reside in the Zope
> DB, and yet manage it through the ZMI.
Yes, I'm working on that as well.
> That is what I have done so far. I created a package called
> “customers”, which has an instance in the Zope DB. It has a view which
> lists all customers from an RDBMS. It creates a link for each customer
> with the customer ID embedded in it.
>
> I would like to create, on the fly, a customer instance from the
> customer ID in the URL. Based upon the ID I could set all the
> attributes of the instance by loading it from a database.
Hmm, I didn't try your approach, sorta faking it with record ids inserting
the view construction. My approach was to create a container component
representing the SQL table and another component representing instances of
records within that table.
class VentureSet(
Persistent, SiteManagerContainer, Contained, SimpleSQLTable):
class Venture(
Location, RelationalRow):
While the container, VentureSet, is persistent within the ZODB, what it
*contains* is constructed dynamically from SQL queries. The ZODB persistent
data is just the connection name itself, nothing more, and the SQL table
name is a class-static attribute. Between those two, each XXXSet class can
find its data table.
def keys(self):
"""Return a sequence-like object containing the names
associated with the objects that appear in the folder
"""
query = "SELECT v_id FROM %s WHERE subset = '%s'" \
% (self.__sqltable__, self.subset)
return [row.v_id for row in self(query)]
The call to self is something I clipped from SQLMethods, to convert the
connection name into an actual connection object, doing a utility lookup,
submitting the query and returning the records:
def __call__(self, query):
try:
connection = self.getConnection()
except KeyError:
raise AttributeError, (
"The database connection '%s' cannot be found." % (
self.connectionName))
cache = getCacheForObject(self)
location = getLocationForCache(self)
if cache and location:
_marker = object()
result = cache.query(location, {'query': query}, default=_marker)
if result is not _marker:
return result
result = queryForResults(connection, query)
if cache and location:
cache.set(result, location, {'query': query})
return result
Here is where a query to the VentureSet container wraps the rows read from
the SQL table into Zope 3 components:
def values(self):
"""Return a sequence-like object containing the objects that
appear in the folder.
"""
query = "SELECT * FROM %s WHERE subset = '%s'" %
(self.__sqltable__, self.subset)
ventures = []
for row in self(query):
venture = Venture(row.v_id, row.legalname, row)
locate(venture, self, row.v_id)
ventures.append(venture)
return ventures
The instances of Venture, which represent the records in the table are
non-persistent as far as the ZODB goes. I did inhert from Location so that
they have a name (primary key) and location (ref to the VentureSet
container) but those attributes are assigned after an SQL query to
instantiate the object.
class Venture(Location, RelationalRow):
The RelationalRow class is my own little lazy accumulator of set-attributes
that get turned into an UPDATE SQL statement at commit time, using:
transaction.get().beforeCommitHook(self.writeMyUnwrittens)
This all gives me a ZMI-manageable object folder of SQL records, and the
URLS look something like (I have similar ledgerset/ledger component pair
underneath the vntureset/venture pair):
http://www.taupro.com/venture/IBM/ledger/100
One trick with this is you have to provide a NameChooser class, from
Philipp's Zope 3 book, to have the VentureSet container defer to the Venture
item for its name, since in Zope 3 items can have names that differ from the
name by which it is known within its container. The NameChooser class is
straight from the book.
I hope this answers your question and if not, I'm glad to share my sourcecode.
I'm looking now at whether I should abandon my home-grown ORM and switch to
sqlos/SQLObject although for what little mine does so far, it's much simpler.
-Jeff
More information about the Zope3-users
mailing list