On Thu, Feb 15, 2007 at 11:50:38AM +0100, Philipp von Weitershausen wrote:
> What's already possible is to have a minimal ZODB with only one 
> persistent object: a SQLObject or SQLAlchemy container. That's a 
> container (e.g. like a folder) whose items aren't persisted in the ZODB 
> but come from a relational database.

This works fine in a Zope 2 / Five world too.  We have apps that have
nothing in the ZODB but a Z*DA instance.  Then we have zope 3 views
and adapters that acquire that instance and use it to talk to the
database, using ZSQL to build the queries. We haven't drunk the ORM
cool-aid yet. :)

In other words: The ZODB may be there but you can pretty much ignore
it if you don't need it :)

> You seem to already have come to the conclusion that having code live in 
> both the filesystem and the ZODB can be painful. I think a good first 
> step for you would be to migrate your remaining ZODB-based code to the 
> filesystem. That not only makes deployment easier, you're also free to 
> refactor it then (e.g. using Zope 3 idioms). In the long run, this also 
> means saying good-bye to things like External Methods because they 
> require code on the filesystem and configuration in the ZODB.


Here's my off-the-cuff attempt at "How To Safely Move A Big Legacy App
Out of the ZODB".

First, get and install FSDump (google for it).

Add a Dumper to a folder containing DTML (it works recursively on
child folders too), configure the Dumper, click the "Save and dump"
button, and voila, there's your code on the filesystem.  It'll store
properties too, in files named like *.metadata.

Then you need a way to use the stuff from the filesystem.
FileSystemSite would be ideal, because it understands those .metadata
files: http://www.infrae.com/download/FileSystemSite

Using it is a bit non-obvious if you're not familiar with CMF, from
which it was extracted.  You'll need to create a minimal Product on
the filesystem that consists of:

- a directory in Products, let's call it Products/mystuff
- an __init__.py at Products/mystuff/__init__.py that looks like this:

   from Products.FileSystemSite.DirectoryView import registerDirectory
   registerDirectory('mysubdir, globals())

- a subdirectory at Products/mystuff/mysubdir.  Put the files and
  directories you dumped in here.

That's it. Restart Zope, add an instance of Filesystem Directory View,
and you'll be prompted for the directory to choose; the only choice
will be the "mysubdir" you registered above. Click OK and you're done.

Check this new Product into source control and rejoice.

One gotcha - files ending in .dtml will be treated as DTML Methods,
not DTML Documents. So if you relied on the semantic difference
between those, you will have some issues to sort out.

Another gotcha - you'll need another plan to deal with those External
Methods, since AFAIK neither Dumper nor FileSystemSite will handle

One expedient if slightly tedious technique would be to just move the
External Method files out of Extensions/ and into
$INSTANCE_HOME/lib/python/.  Then use calls to allow_module() so they
can be imported by through-the-web code (google will tell you more
about that).  Then, delete each external method from the ZMI and in
its place add a Script (Python) with the same id.  Such a script would
have a body something like:

   from my_ext_method_module import myExternalMethodFunction
   return myExternalMethodFunction(arguments)

Once that's done, those scripts can be Dumped into your filesystem
code, and all the DTML that includes calls to them should work.

A final gotcha - if you have ZClasses, I can't help you :)

At this point, you have the same application you started with, it's
just on the filesystem.  Not as clean as a rewrite, but a hell of a
lot more expedient - faster and less risky.

Next you'll want to start adding regression tests to your product
(ZopeTestCase and Zelenium might be useful tools). Then you have a
safety net so you can confidently start refactoring as needed.  *This*
is when you can start thinking about rewriting stuff :-)

I'd put this email somewhere on zopewiki.org, but it seems to be down
at the moment (Bad Gateway).

> It is certainly possible to execute filesystem-based DTML (using
> Globals.DTMLFile).

Right.  But that's a bit of a pain when you have dozens or hundreds of
DTML methods and your first priority is just to get stuff out of the
ZODB and into source control without breaking anything.


Paul Winkler
Zope maillist  -  Zope@zope.org
**   No cross posts or HTML encoding!  **
(Related lists - 
 http://mail.zope.org/mailman/listinfo/zope-dev )

Reply via email to