[Checkins] SVN: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/ Added Demo 2, showing a MessageContainer that is hardwired to accept on messages, instead of subclassing the generic SQLAlchemyContainer.

Michael Bernstein webmaven at cox.net
Tue Jan 16 21:54:48 EST 2007


Log message for revision 72060:
  Added Demo 2, showing a MessageContainer that is hardwired to accept on messages, instead of subclassing the generic SQLAlchemyContainer.
  
  

Changed:
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/README.txt
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/__init__.py
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/__init__.py
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/configure.zcml
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/message.py
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/view.pt
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/configure.zcml
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/container.py
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/interfaces.py
  A   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/message.py
  U   z3c.zalchemy/trunk/src/z3c/zalchemy/demo/z3c.zalchemy.demo-configure.zcml

-=-
Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/README.txt
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/README.txt	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/README.txt	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1,28 @@
+ZAlchemy demos
+==============
+
+These demos show how ZAlchemy can be used to create Zope3 web applications that use SQLAlchemy to persist data in an RDBMS.
+
+To try a demo, copy the included z3c.zalchemy.demo-configure.zcml file to your 
+etc/package-includes/ directory and uncomment the demo you want to try.
+
+Note: Do not try installing more than one of these demos at the same time. Due 
+to a minor bug (hopefully soon eradicated), if ZAlchemy tries to create tables 
+with the same name in different databases it produces an error (because of the
+way the global MetaData() is used as an intermediary).
+
+Because of incompatibilities between the database schemas, each demo defines a 
+different database connection string, to avoid conflicts.
+
+Demo 1: Subclasses the included SQLAlchemyContainer to create a container that
+        is preconfigured to hold only one class (HelloWordMessage)
+        
+Demo 2: Creates a container from scratch that is specialized to only hold one 
+        class (HelloWorldMessage2).
+        
+Demo 3: Demonstrates a rudimentary adapter for storing Dublin Core metadata in 
+        the RDBMS for HelloWorldMessage3 objects.
+        
+Demo 4: Demonstrates a contained HelloWorldMessage4 class that is in itself a
+        container for HelloWorldFragment classes.
+        

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/__init__.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/__init__.py	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/__init__.py	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1 @@
+# Make this a package

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/__init__.py
===================================================================

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/configure.zcml
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/configure.zcml	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/configure.zcml	2007-01-17 02:54:47 UTC (rev 72060)
@@ -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 2"
+    class="z3c.zalchemy.demo.demo_2.container.MessageContainer2"
+    permission="zope.ManageContent"
+    />
+
+  <browser:containerViews
+    for="z3c.zalchemy.demo.demo_2.interfaces.IMessageContainer2"
+    contents="zope.ManageContent"
+    index="zope.View"
+    add="zope.ManageContent"
+    />
+
+<!-- Message -->
+
+  <browser:addMenuItem
+      title="Hello World Message"
+      factory="z3c.zalchemy.demo.demo_2.message.HelloWorldMessage2"
+      view="z3c.zalchemy.demo.demo_2.message.HelloWorldMessage2"
+      permission="zope.ManageContent"
+      />
+
+  <browser:page
+      for="z3c.zalchemy.demo.demo_2.interfaces.IHelloWorldMessage2"
+      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_2.message.HelloWorldMessage2"
+      class=".message.AddHelloWorldMessage"
+      permission="zope.ManageContent" 
+      />
+
+  <browser:page
+    for="z3c.zalchemy.demo.demo_2.interfaces.IHelloWorldMessage2"
+    name="edit.html"
+    class=".message.EditHelloWorldMessage"
+    permission="zope.ManageContent"
+    menu="zmi_views" title="Edit"
+    />
+
+
+</configure>

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/message.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/message.py	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/message.py	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1,31 @@
+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_2.interfaces import IHelloWorldMessage2
+from z3c.zalchemy.demo.demo_2.message import HelloWorldMessage2
+
+#Define the schema for the message ad form
+class AddHelloWorldMessage(form.AddForm):
+
+    form_fields = form.FormFields(IHelloWorldMessage2).omit('__parent__')
+
+    def create(self, data):
+        return HelloWorldMessage2(**data)
+
+# Define the schema for the messag edit form
+class EditHelloWorldMessage(form.EditForm):
+
+    form_fields = form.FormFields(IHelloWorldMessage2).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)
+
+# The template used for the default index.html view
+view_template = NamedTemplateImplementation(
+    ViewPageTemplateFile('view.pt'))

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/view.pt
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/view.pt	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/browser/view.pt	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1,12 @@
+<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>Hello <span tal:replace="context/who">Who</span>!</h1>
+
+</div>
+</body>
+</html>

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/configure.zcml
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/configure.zcml	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/configure.zcml	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1,65 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:alchemy="http://namespaces.zalchemy.org/alchemy">
+
+  <!-- ZAlchemy Setup -->
+
+  <alchemy:engine
+      name="DemoEngine-2"
+      url="sqlite:///zalchemy.message_2.db"
+      />
+  <alchemy:connectTable
+      table="message"
+      engine="DemoEngine-2"
+      />
+  <alchemy:connectClass
+      class=".message.HelloWorldMessage2"
+      engine="DemoEngine-2"
+      />
+
+  <!-- Message Container Configuration -->
+
+  <class class=".container.MessageContainer2">
+
+    <factory
+        id="z3c.zalchemy.demo.demo_2.container.MessageContainer2"
+        title="Message Container 2"
+        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.HelloWorldMessage2">
+    <implements interface="z3c.zalchemy.interfaces.ISQLAlchemyObjectContained" />
+    <require
+      permission="zope.View"
+      interface=".interfaces.IHelloWorldMessage2"
+      />
+
+    <require
+        permission="zope.ManageContent"
+        set_schema=".interfaces.IHelloWorldMessage2"
+        />
+
+  </class>
+
+  <utility
+    component=".message.messageFactory"
+    name="z3c.zalchemy.demo.demo_2.message.HelloWorldMessage2"
+    />
+
+  <include package=".browser" />
+
+</configure>

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/container.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/container.py	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/container.py	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1,89 @@
+from zope.app.container.contained import Contained
+from persistent import Persistent
+from zope.interface import implements
+
+import sqlalchemy
+
+import z3c.zalchemy
+from z3c.zalchemy.container import contained
+
+from interfaces import IMessageContainer2
+from message import HelloWorldMessage2
+
+
+# class that defines a container for storing RDBMS HelloWorlMessage objects
+class MessageContainer2(Persistent, Contained):
+    implements(IMessageContainer2)
+
+    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(HelloWorldMessage2)
+        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(HelloWorldMessage2)
+            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([item])
+
+    def _toStringIdentifier(self, obj):
+        session = z3c.zalchemy.getSession()
+        mapper = session.mapper(HelloWorldMessage2)
+        instance_key = mapper.instance_key(obj)
+        ident = '-'.join(map(str, instance_key[1]))
+        return 'HelloWorldMessage2-'+ident
+
+    def _fromStringIdentifier(self, name):
+        prefix = 'HelloWorldMessage2' + '-'
+        if not name.startswith(prefix):
+            return None
+
+        ident = name[len(prefix):]
+        session = z3c.zalchemy.getSession()
+        return session.query(HelloWorldMessage2).get(ident)
+

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/interfaces.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/interfaces.py	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/interfaces.py	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1,18 @@
+import zope.schema
+from z3c.zalchemy.interfaces import ISQLAlchemyObjectContained, ISQLAlchemyContainer
+from zope.app.container.constraints import contains, containers
+
+# Interface defining the Zope schema for RDBMS-persistent Messages
+class IHelloWorldMessage2(ISQLAlchemyObjectContained):
+    """Information about a hello world message"""
+
+    who = zope.schema.TextLine(
+        title=u'Who',
+        description=u'Name of the person sending the message',
+        required=True)
+
+# Interface of a container for RDBMS-persistent messages
+class IMessageContainer2(ISQLAlchemyContainer):
+    """A container for hello world message mbjects"""
+    contains(IHelloWorldMessage2)
+    

Added: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/message.py
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/message.py	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/demo_2/message.py	2007-01-17 02:54:47 UTC (rev 72060)
@@ -0,0 +1,40 @@
+import sqlalchemy
+import z3c.zalchemy
+from z3c.zalchemy.container import SQLAlchemyNameChooser
+from z3c.zalchemy.interfaces import IAlchemyEngineUtility
+
+from zope.interface import implements
+from zope.schema.fieldproperty import FieldProperty
+
+from interfaces import IHelloWorldMessage2
+
+from zope.component.factory import Factory
+
+# define and create the RDBMS table for storing messages
+HelloWorldMessageTable2 = sqlalchemy.Table(
+        'message', 
+        z3c.zalchemy.metadata,
+        sqlalchemy.Column('id', sqlalchemy.Integer,
+                           primary_key = True),
+        sqlalchemy.Column('who', sqlalchemy.Unicode),
+        )
+
+z3c.zalchemy.createTable('message', 'DemoEngine-2')
+
+#Define the python class for messages
+class HelloWorldMessage2(object):
+    implements(IHelloWorldMessage2)
+
+    who = FieldProperty(IHelloWorldMessage2['who'])
+
+    def __init__(self, who):
+        self.who = who
+
+# Map the message class to the message table
+messagemapper = sqlalchemy.mapper(HelloWorldMessage2, HelloWorldMessageTable2)
+
+messageFactory=Factory(
+    HelloWorldMessage2,
+    title=u"Create a new message",
+    description=u"This factory instantiates new messages"
+    )

Modified: z3c.zalchemy/trunk/src/z3c/zalchemy/demo/z3c.zalchemy.demo-configure.zcml
===================================================================
--- z3c.zalchemy/trunk/src/z3c/zalchemy/demo/z3c.zalchemy.demo-configure.zcml	2007-01-16 20:10:01 UTC (rev 72059)
+++ z3c.zalchemy/trunk/src/z3c/zalchemy/demo/z3c.zalchemy.demo-configure.zcml	2007-01-17 02:54:47 UTC (rev 72060)
@@ -1,5 +1,5 @@
 <configure>
-<include package="z3c.zalchemy.demo.demo_1" />
+<!-- include package="z3c.zalchemy.demo.demo_1" /-->
 <!-- include package="z3c.zalchemy.demo.demo_2" /-->
 <!-- include package="z3c.zalchemy.demo.demo_3" /-->
 <!-- include package="z3c.zalchemy.demo.demo_4" /-->



More information about the Checkins mailing list