[Zope-dev] Porting EMarket to ZPatterns....
Phillip J. Eby
pje@telecommunity.com
Sat, 26 Aug 2000 17:36:52 -0500
At 10:04 AM 8/22/00 -0500, Steve Spicklemire wrote:
>
>Moving this to ZPatterns brings up all sorts of questions. First of all I
no longer
>know that the actual class stored my shopper specialist is a 'Shopper'. It
could
>be any class kept in the shopper manager's rack(s). Soo... my addShopper
should
>probably become:
>
>def addShopper(self, id, REQUEST):
> """ add a new shopper... self is now the shopperManager (Specialist) """
>
> newShopper = self.newItem( id )
>
>
newShopper.propertysheets.methodToUpdatePropertySheetsFromMappingObject(
REQUEST )
Depending on how your framework specifies its requirements for a Shopper,
you probably want something like:
newShopper.propertysheets.get('shopperData').manage_changeProperties(...)
or
newShopper.manage_changeProperties(...)
or
if newShopper.propertysheets.manage_addPropertySheet(id='shopperData',ns=''):
newShopper.propertysheets.get('shopperData').manage_changeProperties(...)
else:
raise 'Unable to add propertysheet'
Notice that you must specifically ask for a particular sheet from the
propertysheets object before trying to change it. Also note that unless
you require users of your framework to make that sheet already available
when a newItem() is created, you must add the sheet yourself.
>Looking through VirtualSheets and PropertySheets code I see __propsets__
>so I was thinking something like:
>
> for prop in newShopper.propertysheets.__propsets__():
> setattr(newShopper, prop, REQUEST.get(prop,None))
Don't do this. __propsets__ is a private method and should not be touched.
If you must iterate through an object's propertysheets, use:
for sheet in newShopper.propertysheets:
...
Which will go through all of the object's property sheets, including
default sheets such as the object's main WebDAV property set.
>but this doesn't seem to work.... (I get 'nameError 'client'') in the
>debugger.... I have no clue where 'client' comes from, reminds me
This looks to me like a problem that someone else reported, and which I
fixed, but it's not fixed in a released version. :( See below:
Index: DataSkins.py
===================================================================
RCS file: /u/idsuser/REPOSITORY/ZProducts/ZPatterns/DataSkins.py,v
retrieving revision 1.49
retrieving revision 1.50
diff -r1.49 -r1.50
377c377
< l.extend(list(sp._PropertySheetsFor(client)))
---
> l.extend(list(sp._PropertySheetsFor(self)))
>of the 'DTML Method' argument called 'client'... but I don't see
>a traceback in the debugger.. anyway.. I've come to something like
>this, though it doesn't do what I need.... :
>
> newShopper = self.newItem(id)
> newShopper.passwd = passwd
>
newShopper.propertysheets.manage_addPropertySheet(id='EMarketProps', ns='')
> emp = newShopper.propertysheets.get('EMarketProps')
> emp.manage_addProperty('email', '', 'string')
> emp.manage_addProperty('name','','string')
> #
> # ... blah blah blah...
> #
> emp.manage_changeProperties(REQUEST)
> self._setObject(id, newShopper)
Actually, this is the correct way to do it, if you are not requiring
shopper objects to have this sheet predefined and available for you. My
suggestion, though, is that you do just that (require the shopper objects
to support what you need).
>I am hopeful that this will expose a glaring misconception of mine
>about propertysheets. ;-) Someone please tell me how stupid I am
>and what I'm missing here... This does me no good... since I have to
>create the propertysheets and I want to allow for properties that
>I *don't know about* (i.e., customizations that individual
>applications need to make these 'shoppers' work as 'clients' or
>'memebrs' or whatever else...) Clearly I'm flailing here..
I don't see that you are. I don't see any problems at all here.
>Any ideas
>from the wizards of Z? How would you modify addShopper to make it
>work with other applications and allow for multiple propertysheets
>that need to be set up from the addShopperForm....
I wouldn't do that. Actually, I think I now see what your actual problem
is. You're trying to implement a whitebox specialist as if it were a
blackbox specialist. A whitebox shouldn't have an add function unless you
want to make it possible for someone to use the whitebox without
customization. If someone wants to have clients (for example), they should
override your addShopperForm to redirect to an addClientForm in their
Clients specialist, and similarly override the other functions of your
Shoppers specialist to delegate to the Clients specialist.
>Also.. I'm hoping for some advice about the old 'Basket' object. Basically
>the old basked object was a simple container, one for each shopper, that
>held 'Basket Items' which were essentially references to MarketItems,
>that were on sale in the store, along with quantity, options, etc..
>How should I work these in with ZPatterns? Should there be a BasketManager
>for each shopper that is essentially a Specialist for BasketItems? Other
>ideas welcome...
I don't have a clear enough idea of your requirements to offer any real
suggestions here. My reaction to the above is basically, "it depends". :)
What do baskets *do*? What do basket items *do*? What are the essential
characteristics of these things which will remain unchanged regardless of
the end-user's application of the framework, versus the changeable
characteristics that are the domain of the application, rather than the
framework.
An example of this sort of analysis happened for me at work recently; doing
requirements gathering for an asset tracking system, it quickly became
clear to me that there were at least 101 uses for such an animal which
would have required it to store data which was not "essential" in the sense
of being universal to all Asset objects. For example, shared hosting
system administrators wanted to know servers' IP addresses, operating
systems, and so on. Dedicated server management people wanted all that
plus what customer was renting the box and whether they'd paid their bill.
Before too long, it became clear that the most useful way to abstract all
this was to allow each Asset to have a Purpose which it was used for.
Purpose is a whitebox which can be mapped to a variety of specific objects
for each kind of application as it is developed - a shared hosting server
Purpose, a dedicated server Purpose, and so on. A unending variety of
objects can be developed which implement the Purpose interface (which
really only needs a description and a link, from the asset management
framework's point of view). These Purposes may be accessed through a
variety of Specialists, each customized with a UI and capabilities
appropriate for its respective audience. Then, through the underlying
database, asset data such as location, serial number, and cost can be
retrieved. Conversely, examining an asset through the asset management
specialists allows display of the description of its current purpose, and a
use history reflecting when it was assigned to different purposes (again,
descriptions only). The descriptions, however, can be rendered as links to
the actual purpose objects, by way of their individual specialists, thus
allowing the user to hop into any of several "vertical" applications tied
into the framework.
In the design on this project, we plan to actually implement a "purposes"
table which will effectively contain nothing more than a key, a
description, and data to be used to link to the "real" purpose object by
way of the correct specialist. Then, depending on the individual
application's needs, other tables may be created (e.g.
dedicated_server_accounts or shared_hosting_servers) which share the same
primary key. The "vertical" specialists will join from this table to
purpose and from there to the asset(s) tied to that purpose. Going the
other way, the asset management system can only join as far as the purposes
table, since it will (should) not need to know how every possible purpose
is implemented. The asset management framework itself will not change as
new purposes for assets are discovered and features to support them are
built into the overall application. This decoupling should allow rapid,
parallel development of new features and subsystems once the core framework
is functional.
Anyway, sorry to babble, but I thought it might be helpful to show an
actual real-life example of framework development with ZPatterns that might
have some principles applicable to your project.