[Checkins] SVN: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/
Added Demo 3. This Demo implements a rudimentary
ZopeDublinCore adapter that persists metadata in the RDBMS
for the Hello World Messages.
Michael Bernstein
webmaven at cox.net
Tue Jan 16 23:05:42 EST 2007
Log message for revision 72062:
Added Demo 3. This Demo implements a rudimentary ZopeDublinCore adapter that persists metadata in the RDBMS for the Hello World Messages.
Changed:
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/__init__.py
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/__init__.py
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/configure.zcml
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/message.py
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/view.pt
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/configure.zcml
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/container.py
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/interfaces.py
A z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/message.py
-=-
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/__init__.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/__init__.py 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/__init__.py 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1 @@
+# Make this a package
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/__init__.py
===================================================================
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/configure.zcml
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/configure.zcml 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/configure.zcml 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1,54 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ >
+
+<!-- Message Container -->
+
+ <browser:addMenuItem
+ title="Message Container 3"
+ class="z3c.zalchemy.demo.demo_3.container.MessageContainer3"
+ permission="zope.ManageContent"
+ />
+
+ <browser:containerViews
+ for="z3c.zalchemy.demo.demo_3.interfaces.IMessageContainer3"
+ contents="zope.ManageContent"
+ index="zope.View"
+ add="zope.ManageContent"
+ />
+
+<!-- Message -->
+
+ <browser:addMenuItem
+ title="Hello World Message"
+ factory="z3c.zalchemy.demo.demo_3.message.HelloWorldMessage3"
+ view="z3c.zalchemy.demo.demo_3.message.HelloWorldMessage3"
+ permission="zope.ManageContent"
+ />
+
+ <browser:page
+ for="z3c.zalchemy.demo.demo_3.interfaces.IHelloWorldMessage3"
+ name="index.html"
+ template="view.pt"
+ permission="zope.View"
+ menu="zmi_views" title="View"
+ />
+
+ <browser:page
+ for="zope.app.container.interfaces.IAdding"
+ name="z3c.zalchemy.demo.demo_3.message.HelloWorldMessage3"
+ class=".message.AddHelloWorldMessage3"
+ permission="zope.ManageContent"
+ />
+
+ <browser:page
+ for="z3c.zalchemy.demo.demo_3.interfaces.IHelloWorldMessage3"
+ name="edit.html"
+ class=".message.EditHelloWorldMessage3"
+ permission="zope.ManageContent"
+ menu="zmi_views" title="Edit"
+ />
+
+
+</configure>
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/message.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/message.py 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/message.py 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1,29 @@
+import zope.traversing.browser
+from zope.app.pagetemplate import ViewPageTemplateFile
+from zope.formlib.namedtemplate import NamedTemplateImplementation
+from zope.formlib import form
+from z3c.zalchemy.demo.demo_3.interfaces import IHelloWorldMessage3
+from z3c.zalchemy.demo.demo_3.message import HelloWorldMessage3
+from zope.dublincore.interfaces import IZopeDublinCore
+
+class AddHelloWorldMessage3(form.AddForm):
+
+ form_fields = form.FormFields(IZopeDublinCore).select('title', 'description')+form.FormFields(IHelloWorldMessage3).omit('__parent__')
+
+ def create(self, data):
+ return HelloWorldMessage3(**data)
+
+class EditHelloWorldMessage3(form.EditForm):
+
+ form_fields = form.FormFields(IZopeDublinCore).select('title', 'description')+form.FormFields(IHelloWorldMessage3).omit('__parent__')
+
+ actions = form.EditForm.actions.copy()
+
+ @form.action(_("Apply and View"))
+ def handle_edit_view_action(self, action, data):
+ self.actions['form.actions.apply'].success(data)
+ url = zope.traversing.browser.absoluteURL(self.context, self.request)
+ self.request.response.redirect(url)
+
+view_template = NamedTemplateImplementation(
+ ViewPageTemplateFile('view.pt'))
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/view.pt
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/view.pt 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/browser/view.pt 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1,13 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
+ metal:use-macro="context/@@standard_macros/view">
+<body>
+<div metal:fill-slot="body">
+
+ <h1 tal:content="context/zope:title">Title</h1>
+ <p tal:content="context/zope:description">The description</p>
+ <h2>Hello <span tal:replace="context/who">Who</span>!</h2>
+</div>
+</body>
+</html>
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/configure.zcml
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/configure.zcml 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/configure.zcml 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1,79 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ xmlns:alchemy="http://namespaces.zalchemy.org/alchemy">
+
+ <!-- ZAlchemy Setup -->
+
+ <alchemy:engine
+ name="DemoEngine-3"
+ url="sqlite:///zalchemy.message_3.db"
+ />
+
+ <alchemy:connectTable
+ table="message"
+ engine="DemoEngine-3"
+ />
+ <alchemy:connectTable
+ table="dublin_core"
+ engine="DemoEngine-3"
+ />
+
+ <alchemy:connectClass
+ class=".message.RelationalDC"
+ engine="DemoEngine-3"
+ />
+ <alchemy:connectClass
+ class=".message.HelloWorldMessage3"
+ engine="DemoEngine-3"
+ />
+
+ <!-- Message Container Configuration -->
+
+ <class class=".container.MessageContainer3">
+
+ <factory
+ id="z3c.zalchemy.demo.demo_3.container.MessageContainer3"
+ title="Message Container 3"
+ description="A container for Hello World Message instances" />
+
+ <require
+ permission="zope.View"
+ interface="zope.app.container.interfaces.IReadContainer"
+ />
+
+ <require
+ permission="zope.ManageContent"
+ interface="zope.app.container.interfaces.IWriteContainer"
+ />
+
+ </class>
+
+
+ <!-- Message Configuration -->
+
+ <class class=".message.HelloWorldMessage3">
+ <implements interface="z3c.zalchemy.interfaces.ISQLAlchemyObjectContained" />
+ <require
+ permission="zope.View"
+ interface=".interfaces.IHelloWorldMessage3"
+ />
+
+ <require
+ permission="zope.ManageContent"
+ set_schema=".interfaces.IHelloWorldMessage3"
+ />
+
+ </class>
+
+ <utility
+ component=".message.messageFactory"
+ name="z3c.zalchemy.demo.demo_3.message.HelloWorldMessage3"
+ />
+
+ <adapter
+ factory=".message.RelationalDCAdapter"
+ permission="zope.View" />
+
+ <include package=".browser" />
+
+</configure>
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/container.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/container.py 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/container.py 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1,86 @@
+from zope.app.container.contained import Contained
+from persistent import Persistent
+from zope.interface import implements
+
+import z3c.zalchemy
+from z3c.zalchemy.container import contained
+
+from interfaces import IMessageContainer3
+from message import HelloWorldMessage3
+
+# Class for the container for storing RDBMS-persistent HelloWorlMessage objects
+class MessageContainer3(Persistent, Contained):
+ implements(IMessageContainer3)
+
+ def keys(self):
+ for name, obj in self.items():
+ yield name
+
+ def values(self):
+ for name, obj in self.items():
+ yield obj
+
+ def __iter__(self):
+ return iter(self.keys())
+
+ def items(self):
+ session = z3c.zalchemy.getSession()
+ query = session.query(HelloWorldMessage3)
+ for obj in query.select():
+ name = self._toStringIdentifier(obj)
+ yield (name, contained(obj, self, name) )
+
+ def __getitem__(self, name):
+ if not isinstance(name, basestring):
+ raise KeyError, "%s is not a string" % name
+ obj = self._fromStringIdentifier(name)
+ if obj is None:
+ raise KeyError(name)
+ return contained(obj, self, name)
+
+ def get(self, name, default=None):
+ try:
+ return self[name]
+ except KeyError:
+ return default
+
+ def __contains__(self, name):
+ return self.get(name) is not None
+
+ def __len__(self):
+ try:
+ session = z3c.zalchemy.getSession()
+ query = session.query(HelloWorldMessage3)
+ return query.count()
+ except sqlalchemy.exceptions.SQLError:
+ # we don't want an exception in case of database problems
+ return 0
+
+ def __delitem__(self, name):
+ obj = self[name]
+ #TODO: better delete objects using a delete adapter
+ # for dependency handling.
+ session = z3c.zalchemy.getSession()
+ session.delete(obj)
+
+ def __setitem__(self, name, item):
+ session = z3c.zalchemy.getSession()
+ session.save(item)
+ session.flush()
+
+ def _toStringIdentifier(self, obj):
+ session = z3c.zalchemy.getSession()
+ mapper = session.mapper(HelloWorldMessage3)
+ instance_key = mapper.instance_key(obj)
+ ident = '-'.join(map(str, instance_key[1]))
+ return 'HelloWorldMessage3-'+ident
+
+ def _fromStringIdentifier(self, name):
+ prefix = 'HelloWorldMessage3' + '-'
+ if not name.startswith(prefix):
+ return None
+
+ ident = name[len(prefix):]
+ session = z3c.zalchemy.getSession()
+ return session.query(HelloWorldMessage3).get(ident)
+
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/interfaces.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/interfaces.py 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/interfaces.py 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1,21 @@
+import zope.schema
+from z3c.zalchemy.interfaces import ISQLAlchemyObjectContained, ISQLAlchemyContainer
+from zope.app.container.constraints import contains, containers
+from zope.interface import Interface, Attribute
+
+# Interface defining the Zope schema of message objects
+class IHelloWorldMessage3(ISQLAlchemyObjectContained):
+ """Information about a hello world message"""
+
+ id = Attribute("The ID of the Message")
+
+ who = zope.schema.TextLine(
+ title=u'Who',
+ description=u'Name of the person getting the message',
+ required=True)
+
+#interface defining the schema of the container for message objects
+class IMessageContainer3(ISQLAlchemyContainer):
+ """A container for hello world message mbjects"""
+ contains(IHelloWorldMessage3)
+
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/message.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/message.py 2007-01-17 03:59:09 UTC (rev 72061)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_3/message.py 2007-01-17 04:05:41 UTC (rev 72062)
@@ -0,0 +1,142 @@
+from datetime import datetime
+
+import sqlalchemy
+
+import z3c.zalchemy
+from z3c.zalchemy.container import SQLAlchemyNameChooser
+
+from zope.interface import implements
+from zope.component import adapts
+from zope.schema.fieldproperty import FieldProperty
+from zope.component.factory import Factory
+from zope.dublincore.interfaces import IZopeDublinCore
+
+from interfaces import IHelloWorldMessage3
+
+# Define and create the table for storing dublin core metadata
+RelationalDCTable = sqlalchemy.Table(
+ 'dublin_core',
+ z3c.zalchemy.metadata,
+ sqlalchemy.Column('id', sqlalchemy.Integer,
+ sqlalchemy.Sequence('metadata_seq'),
+ primary_key = True),
+ sqlalchemy.Column('title', sqlalchemy.Unicode),
+ sqlalchemy.Column('description', sqlalchemy.Unicode),
+ sqlalchemy.Column('created', sqlalchemy.DateTime),
+ sqlalchemy.Column('modified', sqlalchemy.DateTime)
+ )
+
+z3c.zalchemy.createTable('dublin_core', 'DemoEngine-3')
+
+# Define and create the table for storing the message
+# Note the explicit setting of the FK relationship, and that the
+# primary key does *not* autoincrement
+HelloWorldMessageTable3 = sqlalchemy.Table(
+ 'message',
+ z3c.zalchemy.metadata,
+ sqlalchemy.Column('id', sqlalchemy.Integer,
+ sqlalchemy.ForeignKey(RelationalDCTable.c.id),
+ primary_key = True,
+ autoincrement = False),
+ sqlalchemy.Column('who', sqlalchemy.Unicode),
+ )
+
+z3c.zalchemy.createTable('message', 'DemoEngine-3')
+
+# The class defining the object containing the metadata
+class RelationalDC(object):
+
+ creators = FieldProperty(IZopeDublinCore['creators'])
+ title = FieldProperty(IZopeDublinCore['title'])
+ description = FieldProperty(IZopeDublinCore['description'])
+ created = FieldProperty(IZopeDublinCore['created'])
+ modified = FieldProperty(IZopeDublinCore['modified'])
+
+
+ def __init__(self, title=None, description=None, created=None,
+ modified=None):
+ self.title = title
+ self.description = description
+ if created is None:
+ self.created = datetime.now()
+ else:
+ self.created = created
+ if modified is None:
+ self.modified = datetime.now()
+ else:
+ self.modified = modified
+
+# Map the metadata table to the metadata class
+relationalmapper = sqlalchemy.mapper(RelationalDC, RelationalDCTable)
+
+# The class defining the adapter between the message object and the
+# IZopeDublinCore interface.
+class RelationalDCAdapter(object):
+ adapts(IHelloWorldMessage3)
+ implements(IZopeDublinCore)
+
+ # The adapter implementation selects the correct
+ # RelationalDC instance based on the message id.
+ def __init__(self, context):
+ self.context = context
+ self.__parent__ = context
+ session = z3c.zalchemy.getSession()
+ query = session.query(RelationalDC).select_by(id=context.id)
+ self.result = None
+ try:
+ self.result = query[0]
+ except IndexError:
+ pass
+
+ # faking the creators property for now
+ def getCreators(self):
+ return ()
+
+ def setCreators(self, creators):
+ pass
+
+ creators = property(getCreators, setCreators, doc="RelationalDC creators")
+
+ def getTitle(self):
+ return self.result.title
+
+ def setTitle(self, title):
+ self.result.title = title
+
+ title = property(getTitle, setTitle, doc="RelationalDC title")
+
+ def getDescription(self):
+ return self.result.description
+
+ def setDescription(self, description):
+ self.result.description = description
+
+ description = property(getDescription, setDescription,
+ doc="RelationalDC description")
+
+
+# The class defining the message object
+class HelloWorldMessage3(object):
+ implements(IHelloWorldMessage3)
+
+ who = FieldProperty(IHelloWorldMessage3['who'])
+
+ # instantiate a RelationaDC object to get an id
+ # (the metadata.id column autoincrements)
+ def __init__(self, title, description, who):
+ self.rdc = RelationalDC(title, description)
+ self.who = who
+
+
+# map the message class to the mesage table
+messagemapper = sqlalchemy.mapper(HelloWorldMessage3, HelloWorldMessageTable3)
+# add an additional property to the message mapper that maps
+# to the metadata class
+messagemapper.add_property('rdc', sqlalchemy.relation(RelationalDC,
+ cascade="delete"))
+
+messageFactory=Factory(
+ HelloWorldMessage3,
+ title=u"Create a new message",
+ description=u"This factory instantiates new messages"
+ )
More information about the Checkins
mailing list