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" | ||||
|   <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
	
	 helmutm
						helmutm