use formlib for creating a new loops site; automatically create subobjects
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1246 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
f6f863eeb6
commit
db5a60a6a3
10 changed files with 223 additions and 41 deletions
|
@ -28,11 +28,14 @@ from zope.app.form.browser.interfaces import ITerms
|
|||
from zope.app.intid.interfaces import IIntIds
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
from zope.dottedname.resolve import resolve
|
||||
from zope.formlib.form import FormFields
|
||||
from zope.formlib.form import EditForm as BaseEditForm
|
||||
from zope.formlib.form import AddForm as BaseAddForm
|
||||
from zope.formlib.namedtemplate import NamedTemplate
|
||||
from zope.interface import implements
|
||||
from zope.interface import Interface, implements
|
||||
from zope.app.publisher.browser import applySkin
|
||||
from zope.publisher.interfaces.browser import ISkin
|
||||
from zope import schema
|
||||
from zope.schema.vocabulary import SimpleTerm
|
||||
from zope.security import canAccess, canWrite
|
||||
from zope.security.proxy import removeSecurityProxy
|
||||
|
@ -40,6 +43,29 @@ from zope.security.proxy import removeSecurityProxy
|
|||
from cybertools.typology.interfaces import IType
|
||||
from loops.interfaces import IView
|
||||
from loops import util
|
||||
from loops.util import _
|
||||
|
||||
|
||||
class NameField(schema.ASCIILine):
|
||||
|
||||
def _validate(self, value):
|
||||
super(NameField, self)._validate(value)
|
||||
|
||||
|
||||
class IAddForm(Interface):
|
||||
|
||||
name = NameField(
|
||||
title=_(u'Object name'),
|
||||
description=_(u'Name of the object - will be used for addressing the '
|
||||
'object via a URL; should therefore be unique within '
|
||||
'the container and not contain special characters')
|
||||
)
|
||||
|
||||
|
||||
class AddForm(BaseAddForm):
|
||||
|
||||
form_fields = FormFields(IAddForm)
|
||||
template = NamedTemplate('loops.pageform')
|
||||
|
||||
|
||||
class EditForm(BaseEditForm):
|
||||
|
|
|
@ -85,13 +85,11 @@
|
|||
|
||||
<!-- loops top-level container -->
|
||||
|
||||
<addform
|
||||
label="Add loops Container"
|
||||
<page
|
||||
name="AddLoopsContainer.html"
|
||||
schema="loops.interfaces.ILoops"
|
||||
content_factory="loops.Loops"
|
||||
template="add.pt"
|
||||
permission="zope.ManageContent"
|
||||
for="zope.app.container.interfaces.IAdding"
|
||||
class="loops.browser.manager.LoopsAddForm"
|
||||
permission="zope.ManageApplication"
|
||||
/>
|
||||
|
||||
<addMenuItem
|
||||
|
@ -108,14 +106,13 @@
|
|||
add="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<editform
|
||||
label="Edit Loops Container"
|
||||
<page
|
||||
name="edit.html"
|
||||
schema="loops.interfaces.ILoops"
|
||||
fields="skinName"
|
||||
for="loops.interfaces.ILoops"
|
||||
permission="zope.ManageContent"
|
||||
menu="zmi_views" title="Edit" />
|
||||
class="loops.browser.manager.LoopsEditForm"
|
||||
permission="zope.ManageApplication"
|
||||
menu="zmi_views" title="Edit"
|
||||
/>
|
||||
|
||||
<!-- concept manager -->
|
||||
|
||||
|
|
60
browser/manager.py
Normal file
60
browser/manager.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
#
|
||||
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
"""
|
||||
Definition of view classes for the top-level loops container.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope.app import zapi
|
||||
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
|
||||
from zope.event import notify
|
||||
from zope.formlib.form import FormFields
|
||||
from loops import Loops
|
||||
from loops.interfaces import ILoops
|
||||
from loops.browser.common import AddForm, EditForm, BaseView
|
||||
from loops.setup import ISetupManager
|
||||
from loops.util import _
|
||||
|
||||
|
||||
class LoopsAddForm(AddForm):
|
||||
|
||||
form_fields = AddForm.form_fields + FormFields(ILoops)
|
||||
label = _(u'Create Loops Site')
|
||||
|
||||
def createAndAdd(self, data):
|
||||
container = self.context.context
|
||||
name = data.pop('name', 'loopsdemo')
|
||||
loops = Loops()
|
||||
self.context.contentName = name
|
||||
for attr in data:
|
||||
setattr(loops, attr, data[attr])
|
||||
notify(ObjectCreatedEvent(loops))
|
||||
self.context.add(loops)
|
||||
setup = ISetupManager(loops, None)
|
||||
if setup is not None:
|
||||
setup.setup()
|
||||
return loops
|
||||
|
||||
|
||||
class LoopsEditForm(EditForm):
|
||||
|
||||
form_fields = FormFields(ILoops)
|
||||
|
||||
|
|
@ -41,12 +41,16 @@ function toggleFormFieldHelp(ob,state) {
|
|||
|
||||
<div id="viewspace" metal:define-slot="viewspace">
|
||||
|
||||
<h1 i18n:translate="heading_editform"
|
||||
metal:define-slot="heading">Edit
|
||||
<h1 tal:condition="not:view/label"
|
||||
i18n:translate="heading_editform"
|
||||
metal:define-slot="heading">Edit
|
||||
<span i18n:name="title"
|
||||
tal:content="context/title">Concept</span>
|
||||
tal:content="context/title|context/zope:name">Concept</span>
|
||||
</h1>
|
||||
|
||||
<h1 tal:condition="view/label"
|
||||
tal:content="view/label">Headline</h1>
|
||||
|
||||
<metal:block define-macro="header">
|
||||
|
||||
<div class="form-status"
|
||||
|
|
|
@ -284,6 +284,7 @@
|
|||
</class>
|
||||
|
||||
|
||||
<adapter factory="loops.setup.SetupManager" />
|
||||
<adapter factory="loops.external.NodesLoader" />
|
||||
<adapter factory="loops.external.NodesExporter" />
|
||||
<adapter factory="loops.external.NodesImporter" />
|
||||
|
|
46
helpers.txt
46
helpers.txt
|
@ -19,26 +19,30 @@ Let's first do some basic imports
|
|||
>>> from zope.interface import Interface
|
||||
>>> from zope.publisher.browser import TestRequest
|
||||
|
||||
and setup a simple loops site with its manager objects,
|
||||
and provide a relation registry:
|
||||
|
||||
>>> from cybertools.relation.interfaces import IRelationRegistry
|
||||
>>> from cybertools.relation.registry import DummyRelationRegistry
|
||||
>>> from zope.app.testing import ztapi
|
||||
>>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry())
|
||||
|
||||
Now we can setup a simple loops site with its manager objects, using a
|
||||
loops setup manager:
|
||||
|
||||
>>> from loops import Loops
|
||||
>>> site['loops'] = Loops()
|
||||
>>> loopsRoot = site['loops']
|
||||
|
||||
>>> from loops.concept import ConceptManager, Concept
|
||||
>>> loopsRoot['concepts'] = ConceptManager()
|
||||
>>> from loops.setup import SetupManager
|
||||
>>> setup = SetupManager(loopsRoot)
|
||||
>>> setup.setup()
|
||||
>>> concepts = loopsRoot['concepts']
|
||||
|
||||
>>> from loops.resource import ResourceManager, Document, MediaAsset
|
||||
>>> loopsRoot['resources'] = ResourceManager()
|
||||
>>> resources = loopsRoot['resources']
|
||||
|
||||
>>> from loops.view import ViewManager, Node
|
||||
>>> loopsRoot['views'] = ViewManager()
|
||||
>>> views = loopsRoot['views']
|
||||
|
||||
some concepts,
|
||||
We also add some example concepts,
|
||||
|
||||
>>> from loops.concept import Concept
|
||||
>>> cc1 = Concept(u'Zope')
|
||||
>>> concepts['cc1'] = cc1
|
||||
>>> cc1.title
|
||||
|
@ -51,6 +55,7 @@ some concepts,
|
|||
|
||||
resources,
|
||||
|
||||
>>> from loops.resource import Document, MediaAsset
|
||||
>>> doc1 = Document(u'Zope Info')
|
||||
>>> resources['doc1'] = doc1
|
||||
>>> doc1.title
|
||||
|
@ -61,6 +66,7 @@ resources,
|
|||
|
||||
and nodes (in view space):
|
||||
|
||||
>>> from loops.view import Node
|
||||
>>> m1 = Node(u'Home')
|
||||
>>> views['m1'] = m1
|
||||
>>> m1.nodeType = 'menu'
|
||||
|
@ -69,12 +75,6 @@ and nodes (in view space):
|
|||
>>> m1['p1'] = m1p1
|
||||
>>> m1p1.nodeType = 'page'
|
||||
|
||||
Finally, we also need a relation registry:
|
||||
|
||||
>>> from cybertools.relation.interfaces import IRelationRegistry
|
||||
>>> from cybertools.relation.registry import DummyRelationRegistry
|
||||
>>> from zope.app.testing import ztapi
|
||||
>>> ztapi.provideUtility(IRelationRegistry, DummyRelationRegistry())
|
||||
|
||||
Type management with typology
|
||||
=============================
|
||||
|
@ -98,11 +98,10 @@ As we have not yet associated a type with one of our content objects we get
|
|||
>>> cc1_type.token
|
||||
'.unknown'
|
||||
|
||||
So we create two special concepts: one ('hasType') as the predicate signifying
|
||||
a type relation, and the other ('type') as the one and only type concept:
|
||||
During setup we created two special concepts: one ('hasType') as the predicate
|
||||
signifying a type relation, and the other ('type') as the one and only type
|
||||
concept:
|
||||
|
||||
>>> concepts['hasType'] = Concept(u'has type')
|
||||
>>> concepts['type'] = Concept(u'Type')
|
||||
>>> typeObject = concepts['type']
|
||||
|
||||
Assigning a type to a concept is a core functionality of concepts as
|
||||
|
@ -189,8 +188,9 @@ get a type manager from all loops objects, always with the same context:
|
|||
|
||||
>>> types = typeManager.types
|
||||
>>> sorted(t.token for t in types)
|
||||
['.loops/concepts/topic', '.loops/concepts/type',
|
||||
'loops.resource.Document', 'loops.resource.MediaAsset']
|
||||
['.loops/concepts/predicate', '.loops/concepts/topic',
|
||||
'.loops/concepts/type', 'loops.resource.Document',
|
||||
'loops.resource.MediaAsset']
|
||||
|
||||
>>> typeManager.getType('.loops/concepts/topic') == cc1_type
|
||||
True
|
||||
|
@ -200,7 +200,7 @@ condition:
|
|||
|
||||
>>> types = typeManager.listTypes(include=('concept',))
|
||||
>>> sorted(t.token for t in types)
|
||||
['.loops/concepts/topic', '.loops/concepts/type']
|
||||
['.loops/concepts/predicate', '.loops/concepts/topic', '.loops/concepts/type']
|
||||
>>> types = typeManager.listTypes(exclude=('concept',))
|
||||
>>> sorted(t.token for t in types)
|
||||
['loops.resource.Document', 'loops.resource.MediaAsset']
|
||||
|
|
|
@ -32,8 +32,7 @@ from zope.app.folder.interfaces import IFolder
|
|||
from cybertools.relation.interfaces import IRelation
|
||||
|
||||
import util
|
||||
|
||||
_ = MessageFactory('loops')
|
||||
from util import _
|
||||
|
||||
|
||||
# common interfaces
|
||||
|
|
86
setup.py
Normal file
86
setup.py
Normal file
|
@ -0,0 +1,86 @@
|
|||
#
|
||||
# Copyright (c) 2006 Helmut Merz helmutm@cy55.de
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
"""
|
||||
Automatic setup of a loops site.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
import transaction
|
||||
from zope.app.event.objectevent import ObjectCreatedEvent, ObjectModifiedEvent
|
||||
from zope.event import notify
|
||||
from zope.component import adapts
|
||||
from zope.interface import implements, Interface
|
||||
from zope.cachedescriptors.property import Lazy
|
||||
|
||||
from loops.interfaces import ILoops
|
||||
from loops.concept import ConceptManager, Concept
|
||||
from loops.resource import ResourceManager
|
||||
from loops.view import ViewManager, Node
|
||||
|
||||
|
||||
class ISetupManager(Interface):
|
||||
""" An object that controls the setup of a loops site.
|
||||
"""
|
||||
|
||||
def setup():
|
||||
""" Set up a loops site: create all necessary objects and the
|
||||
relations between them.
|
||||
"""
|
||||
|
||||
|
||||
class SetupManager(object):
|
||||
|
||||
adapts(ILoops)
|
||||
implements(ISetupManager)
|
||||
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
def setup(self):
|
||||
concepts, resources, views = self.setupManagers()
|
||||
self.setupCoreConcepts(concepts)
|
||||
|
||||
def setupManagers(self):
|
||||
loopsRoot = self.context
|
||||
concepts = self.addObject(loopsRoot, ConceptManager, 'concepts')
|
||||
resources = self.addObject(loopsRoot, ResourceManager, 'resources')
|
||||
views = self.addObject(loopsRoot, ViewManager, 'views')
|
||||
return concepts, resources, views
|
||||
|
||||
def setupCoreConcepts(self, conceptManager):
|
||||
typeConcept = self.addObject(conceptManager, Concept, 'type', u'Type')
|
||||
hasType = self.addObject(conceptManager, Concept, 'hasType', u'has type')
|
||||
predicate = self.addObject(conceptManager, Concept, 'predicate', u'Predicate')
|
||||
standard = self.addObject(conceptManager, Concept, 'standard', u'subobject')
|
||||
typeConcept.conceptType = typeConcept
|
||||
predicate.conceptType = typeConcept
|
||||
hasType.conceptType = predicate
|
||||
standard.conceptType = predicate
|
||||
|
||||
def addObject(self, container, class_, name, title=None):
|
||||
if name in container:
|
||||
return container[name]
|
||||
if title:
|
||||
obj = container[name] = class_(title)
|
||||
else:
|
||||
obj = container[name] = class_()
|
||||
notify(ObjectCreatedEvent(obj))
|
||||
notify(ObjectModifiedEvent(obj))
|
||||
return obj
|
|
@ -17,6 +17,12 @@ from loops.concept import Concept, ConceptManager
|
|||
from loops.resource import Document, MediaAsset, ResourceManager
|
||||
from loops.view import Node, ViewManager
|
||||
|
||||
# just for making sure there aren't any syntax and other errors during
|
||||
# Zope startup:
|
||||
|
||||
from loops.browser.manager import LoopsAddForm, LoopsEditForm
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
"Basic tests for the loops package."
|
||||
|
||||
|
|
3
util.py
3
util.py
|
@ -23,9 +23,12 @@ $Id$
|
|||
"""
|
||||
|
||||
from zope.interface import directlyProvides, directlyProvidedBy
|
||||
from zope.i18nmessageid import MessageFactory
|
||||
from zope.schema import vocabulary
|
||||
#from view import TargetRelation
|
||||
|
||||
_ = MessageFactory('loops')
|
||||
|
||||
|
||||
class KeywordVocabulary(vocabulary.SimpleVocabulary):
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue