[z3-checkins] r5838 - z3/sqlos/trunk
dreamcatcher at codespeak.net
dreamcatcher at codespeak.net
Sat Jul 31 18:12:51 MEST 2004
Author: dreamcatcher
Date: Sat Jul 31 18:12:51 2004
New Revision: 5838
Modified:
z3/sqlos/trunk/README.txt
Log:
Merge 'dman' patch to README.txt
Modified: z3/sqlos/trunk/README.txt
==============================================================================
--- z3/sqlos/trunk/README.txt (original)
+++ z3/sqlos/trunk/README.txt Sat Jul 31 18:12:51 2004
@@ -6,6 +6,9 @@
:Date: $Date$
:Version: $Rev$
+Background
+----------
+
This file describes how to use the ``sqlos`` package to use
SQLObject together with Zope 3.
@@ -43,6 +46,24 @@
its flexible enough that you can make their objects come from any
connection and any registered class you wish.
+Dependencies
+------------
+
+ + SQLObject >= 0.6
+
+ Place the sqlobject package somewhere in python's sys.path
+ ($ZOPEHOME/lib/python is a good location).
+
+ + Zope Database Adapter
+
+ Install the adapter appropriate for your database backend. For
+ example, install the ``psycopgda`` package to connect to PostgreSQL.
+ The ``pyscopgda`` package is located in the zopeproducts_ CVS
+ repository.
+
+.. _zopeproducts: http://cvs.zope.org/zopeproducts/
+
+
Setting up a connection for SQLObject
-------------------------------------
@@ -64,6 +85,7 @@
</configure>
+
Making SQLObject-based objects editable inside Zope
---------------------------------------------------
@@ -78,17 +100,21 @@
from zope.interface import implements
from sqlobject import *
+ from sqlos import SQLOS
from myproject.interfaces import IPerson
- class Person(SQLObject):
+ class Person(SQLOS):
implements(IPerson)
- _columns = [StringCol('username', length=20, notNull=1),]
+ _columns = [StringCol('username', length=20, notNull=True),
+ StringCol('fname', length=20, notNull=True),
+ StringCol('lname', length=20, notNull=True),]
Here you can see that there is almost nothing special needed for
making the object be recognized by Zope 3. In fact, if you remove the
-``implements(IPerson)`` line, it is **exactly** the same code you
+``implements(IPerson)`` line, and inherit from SQLObject directly
+instead of SQLOS, it is **exactly** the same code you
would use for a standard SQLObject class (Note: if you want, you can
declare that an object implements a given interface in a separate
file, or even in ZCML).
@@ -103,15 +129,19 @@
id = Attribute('Id')
username = TextLine(title=u'Username',
description=u'The name of the user')
+ fname = TextLine(title=u'Given Name',
+ description=u'The given name of the user')
+ lname = TextLine(title=u'Surname',
+ description=u'The surname of the user')
As you can see, there's not much here either. We're just saying that
classes that implement IPerson will have an ``id`` attribute (all
SQLObject instance have that by default) and a ``username`` attribute,
-which happens to be a ``TextLine`` (well see more about that later)
+which happens to be a ``TextLine`` (we'll see more about that later)
with a label and a description.
-This interface is used to auto-generate the edit forms inside Zope
-3. Let`s see what is needed to do that::
+This interface is used to auto-generate the edit forms inside Zope 3.
+Let's see what is needed to do that::
<configure
xmlns='http://namespaces.zope.org/zope'
@@ -119,19 +149,19 @@
xmlns:sqlos='http://namespaces.sqlobject.org/sqlos'>
<browser:editform
- schema="myproduct.interfaces.IPerson"
+ schema="myproject.interfaces.IPerson"
name="edit.html"
menu="zmi_views"
label="Edit a Person"
permission="zope.ManageContent"
/>
- <content class="myproduct.person.Person">
+ <content class="myproject.person.Person">
<require
permission="zope.ManageContent"
- interface="myproduct.interfaces.IPerson"
- set_schema="myproduct.interfaces.IPerson"
+ interface="myproject.interfaces.IPerson"
+ set_schema="myproject.interfaces.IPerson"
/>
</content>
@@ -179,8 +209,143 @@
``set_schema`` on the interface, you won`t be able to modify the
instance.
+
+Create A Container
+------------------
+
+In addition to defining the content for Zope, you need a place for
+zope to locate the content. ``sqlos`` already provides nearly all of
+the implementation in the SQLObjectContainer class, however this
+ready-made container is constrained such that it can not contain any
+content. SQLObjectContainer must be extended to adjust this
+constraint and make the data in the database appear to be in this
+container.
+
+As always, the first step is to declare the interface::
+
+ from zope.app.container.constraints import ItemTypePrecondition
+ from sqlos.interfaces.container import ISQLObjectContainer
+ from myproject.interfaces import IPerson
+
+ class IPersonContainer(ISQLObjectContainer) :
+
+ def __setitem__(name, item) :
+ pass
+ __setitem__.precondition = ItemTypePrecondition( IPerson )
+
+The zope container infrastructure checks the __setitem__ precondition
+to determine what type of content the container is allowed to contain.
+
+Next, define the implementation::
+
+ from sqlos.container import SQLObjectContainer
+ from myproject.interfaces import IPersonContainer
+
+ class PersonContainer(SQLObjectContainer) :
+ implements(IPersonContainer)
+
+All that needs to be done at this point is to connect an
+implementation with the interface. SQLObjectContainer provides all
+the (core) logic necessary. Later you may want to add custom methods
+and logic for convenience in manipulating the SQL-backed records.
+
+Finally, write the ZCML configuration to put all the pieces together::
+
+ <content class="myproject.PersonContainer">
+
+ <implements interface="zope.app.container.interfaces.IContentContainer" />
+
+ <factory
+ id="myproject.PersonContainer"
+ title="PersonEntry Container"
+ description="A container for SQLObject instances" />
+
+ <require
+ permission="zope.View"
+ interface="zope.app.container.interfaces.IReadContainer"
+ />
+
+ <require
+ permission="zope.ManageContent"
+ interface="zope.app.container.interfaces.IWriteContainer"
+ />
+
+ <require
+ permission="zope.View"
+ attributes="select"
+ />
+
+ </content>
+
+ <browser:addMenuItem
+ class="myproject.PersonContainer"
+ title="Person Container"
+ description="A persistent container for SQL-backed Person objects"
+ permission="zope.ManageContent"
+ />
+
+
+Demonstration
+-------------
+
+At this point you have a complete web interface for your database.
+It is time to test it and demonstrate that it does, indeed, work.
+
+Start zope and point your browser to the ZMI. In the list of addable
+items on the left you should see our ``Person Container`` type. Add
+``Person Container`` to your site. When you view the container's
+@@contents.html view, you should see a simple listing of all the
+people in your database.
+
+
+A Nice Touch (Title / DublinCore)
+---------------------------------
+
+Although the base @@contents.html view is fully functional, it leaves
+plenty of usability to be desired. You will almost certainly want to
+replace the built-in container contents listing with a custom view
+tailored to the type of content your container handles. However, the
+built-in contents can trivially be given a nice touch that vastly
+improves the usability. The view queries the content for its
+DublinCore_ metadata, such as Title. We will provide this metadata
+with an adapter to adapt the IPerson interface to IZopeDublinCore.
+
+The code is as follows::
+
+ from zope.app.dublincore.interfaces import IZopeDublinCore
+
+ class PersonDublinCore(object):
+ """An adapter providing DublinCore metadata for IPerson objects"""
+
+ implements(IZopeDublinCore)
+ __used_for__ = IPerson
+
+ def __init__(self, context):
+ self.context = context
+
+ def Title(self) :
+ return "%s, %s" % (self.context.lname, self.context.fname)
+
+ title = property(Title)
+
+
+
+ <adapter
+ provides="zope.app.dublincore.interfaces.IZopeDublinCore"
+ for="myproject.interfaces.IPerson"
+ factory="myproject.PersonDublinCore"
+ trusted="true"
+ />
+
+.. _DublinCore: http://dublincore.org
+
+
+SQLObjectAuthSource
+-------------------
+
XXX Write about SQLObjectAuthSource.
+
Notes about transaction interoperability
----------------------------------------
More information about the z3-checkins
mailing list