"Phillip J. Eby" wrote:
At 07:30 PM 3/30/01 -0800, Michael R. Bernstein wrote:
Well, I want to store several versions of each image. Let's take a simplified case where I want the original image and a thumbnail, both of which need to appear as subobjects of the ZClass with the meta-data.
Aha. I think I understand what you're doing now. You have an "Image" and you have a "Rendering". Two classes, different behaviors. I'm assuming that originals and thumbnails and whatever other renderings exist have no real behavioral differences and can be implemented with the same class and storage characteristics.
The terminology I'm using is ArchiveImage (for the 'Image' class) and RackImage (for the 'Rendering' class). I think that different sizes would have the same behavioural characteristics (simply an image file, really), but am less sure about storage. My application will attempt to store all the renderings in the ZODB, but if I want this to be reusable, I have to assume that someone (including me) might want to store the image data on the FS instead. If it's going to be stored on the FS, it would be natural to dump different sizes into separate directories, or even separate partitions. Two years from now, this web application could contain around 300 Gb of images (current prices on that much storage are about $1,000 for ten 30 Gb hard-drives, so I'm not too worried on that score).
If I store all the RackImages (originals and thumbnails) in one Rack, how do I differentiate between them, so that '/Archive/001/thumbnail' and 'Archive/001/original' show the appropriate images? It just seemed simpler to create a 'thumbnail' Rack and an 'original' Rack.
It sounds to me like you want an Images specialist and a Renderings specialist, with the latter contained within the former (because Renderings are only accessed by way of Images). Your Image class should have a "getRendering(kind)" method which accesses the renderings specialist to retrieve a rendering, and it can also have a __bobo_traverse__ method that uses getRendering to allow traversal as you describe. This would still be completely storage independent, since that's hidden in the Renderings specialist. Likewise, when your Images create renderings, they'll need to delegate the actual creation to the Renderings specialist.
Thanks, that's *very* helpful. I'm not too certain how to accomplish the 'getRendering(kind)' and the '__bobo_traverse__' magic, But I'll cross that bridge a little later.
If you need different classes for different kinds of renderings, you'll need multiple racks inside the Renderings specialist, but if renderings are basically just a Zope Image object, you can just use a single Rack (and make your id values something like '001_original', '002_thumbnail', etc. and construct these in your getRendering() method).
That's what I meant, sorry. The RackImages need to appear to be attributes of the ZClass, and I'll use SkinScripts to accomplish that.
That's really only practical if you have a fixed set of rendering types and names, but it'll work for retrieval. It won't really help you with creation and assignment, though. I'd suggest specialized methods on Image which delegate to the Renderings specialist.
I was thinking of a manage_upload method on the ArchiveImage, that iterated through a list of sizes and used an external method that imports PIL to resize the image data, then passes the resized image data into the RackImage manage_upload method. Does that seem reasonable? Thanks, Michael Bernstein.