Work in progress: working with target objects
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1041 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
3cbba1d593
commit
b02329358a
10 changed files with 144 additions and 36 deletions
33
README.txt
33
README.txt
|
@ -30,6 +30,8 @@ top-level loops container and a concept manager:
|
|||
>>> concepts['cc1'] = cc1
|
||||
>>> cc1.title
|
||||
u''
|
||||
>>> loopsRoot.getLoopsUri(cc1)
|
||||
'.loops/concepts/cc1'
|
||||
|
||||
>>> cc2 = Concept(u'Zope 3')
|
||||
>>> concepts['cc2'] = cc2
|
||||
|
@ -277,13 +279,17 @@ target may be moved or renamed without any problems.)
|
|||
>>> nodeConfig = INodeConfigSchema(m111)
|
||||
|
||||
>>> nodeConfig.targetUri
|
||||
u'.loops/concepts/cc2'
|
||||
'.loops/concepts/cc2'
|
||||
>>> nodeConfig.title = u'New title for m111'
|
||||
>>> nodeConfig.title
|
||||
u'New title for m111'
|
||||
>>> m111.title
|
||||
u'New title for m111'
|
||||
>>> nodeConfig.targetUri = '.loops/resources/doc1'
|
||||
|
||||
We have to get a new adapter to avoid problems with lazy variables:
|
||||
|
||||
>>> nodeConfig = INodeConfigSchema(m111)
|
||||
>>> nodeConfig.title = 'New title for m111'
|
||||
>>> m111.target is doc1
|
||||
True
|
||||
|
@ -305,12 +311,22 @@ application uses a subclass that does all the other stuff for form handling.)
|
|||
>>> form = {'field.createTarget': True,
|
||||
... 'field.targetUri': '.loops/resources/ma07',
|
||||
... 'field.targetType': 'loops.resource.MediaAsset'}
|
||||
>>> view = ConfigureBaseView(INodeConfigSchema(m111), TestRequest(form=form))
|
||||
>>> view = ConfigureBaseView(m111, TestRequest(form=form))
|
||||
>>> view.checkCreateTarget()
|
||||
>>> m111.target = view.checkCreateTarget()
|
||||
>>> sorted(resources.keys())
|
||||
[u'doc1', u'ma07']
|
||||
|
||||
>>> isinstance(resources['ma07'], MediaAsset)
|
||||
True
|
||||
|
||||
>>> form = {'field.createTarget': True,
|
||||
... 'field.targetType': 'loops.resource.Document'}
|
||||
>>> view = ConfigureBaseView(m111, TestRequest(form=form))
|
||||
>>> m111.target = view.checkCreateTarget()
|
||||
>>> sorted(resources.keys())
|
||||
[u'doc1', u'm1.m11.m111', u'ma07']
|
||||
>>> isinstance(resources['m1.m11.m111'], Document)
|
||||
True
|
||||
|
||||
It is also possible to edit a target's attributes directly in an
|
||||
edit form provided by the node:
|
||||
|
||||
|
@ -318,6 +334,11 @@ edit form provided by the node:
|
|||
>>> ztapi.provideAdapter(INode, IDocument, DocumentProxy)
|
||||
>>> ztapi.provideAdapter(INode, IMediaAsset, MediaAssetProxy)
|
||||
|
||||
>>> proxy = zapi.getAdapter(m111, IDocument)
|
||||
>>> proxy.title = u'Set via proxy'
|
||||
>>> resources['m1.m11.m111'].title
|
||||
u'Set via proxy'
|
||||
|
||||
Ordering Nodes
|
||||
--------------
|
||||
|
||||
|
@ -335,10 +356,10 @@ to the bottom, and to the top
|
|||
|
||||
>>> from cybertools.container.ordered import OrderedContainerView
|
||||
>>> view = OrderedContainerView(m11, TestRequest())
|
||||
>>> view.moveToBottom(('m113',))
|
||||
>>> view.move_bottom(('m113',))
|
||||
>>> m11.keys()
|
||||
['m111', 'm112', 'm114', 'm113']
|
||||
>>> view.moveUp(('m114',), 1)
|
||||
>>> view.move_up(('m114',), 1)
|
||||
>>> m11.keys()
|
||||
['m111', 'm114', 'm112', 'm113']
|
||||
|
||||
|
|
|
@ -23,8 +23,9 @@
|
|||
$Id$
|
||||
"""
|
||||
|
||||
from zope.interface import implements
|
||||
from zope.app import zapi
|
||||
from zope.app.folder.folder import Folder
|
||||
from zope.interface import implements
|
||||
from interfaces import ILoops
|
||||
|
||||
class Loops(Folder):
|
||||
|
@ -34,3 +35,9 @@ class Loops(Folder):
|
|||
def getLoopsRoot(self):
|
||||
return self
|
||||
|
||||
def getViewManager(self):
|
||||
return self['views']
|
||||
|
||||
def getLoopsUri(self, obj):
|
||||
return str('.loops' + zapi.getPath(obj)[len(zapi.getPath(self)):])
|
||||
|
||||
|
|
|
@ -247,7 +247,6 @@
|
|||
<containerViews
|
||||
for="loops.interfaces.IViewManager"
|
||||
index="zope.ManageContent"
|
||||
contents="zope.ManageContent"
|
||||
add="zope.ManageContent"
|
||||
/>
|
||||
|
||||
|
@ -274,6 +273,7 @@
|
|||
content_factory="loops.view.Node"
|
||||
schema="loops.interfaces.INodeConfigSchema"
|
||||
fields="title description nodeType targetType targetUri createTarget"
|
||||
class="loops.browser.node.ConfigureView"
|
||||
permission="zope.ManageContent">
|
||||
|
||||
<widget field="description" height="2" />
|
||||
|
@ -304,6 +304,12 @@
|
|||
|
||||
</editform>
|
||||
|
||||
<containerViews
|
||||
for="loops.interfaces.INode"
|
||||
index="zope.ManageContent"
|
||||
add="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<editform
|
||||
label="Configure Node"
|
||||
name="configure.html"
|
||||
|
@ -320,6 +326,21 @@
|
|||
|
||||
</editform>
|
||||
|
||||
<editform
|
||||
label="Edit Target"
|
||||
name="edit_target.html"
|
||||
schema="loops.interfaces.IMediaAsset"
|
||||
fields="title data contentType"
|
||||
for="loops.interfaces.INode"
|
||||
permission="zope.ManageContent"
|
||||
/>
|
||||
|
||||
<menuItem
|
||||
for="loops.interfaces.INode"
|
||||
menu="zmi_views" action="edit_target.html" title="Edit Target"
|
||||
filter="context/target"
|
||||
/>
|
||||
|
||||
<page
|
||||
name="node.html"
|
||||
for="loops.interfaces.INode"
|
||||
|
@ -333,10 +354,4 @@
|
|||
name="node.html"
|
||||
/>
|
||||
|
||||
<containerViews
|
||||
for="loops.interfaces.IBaseNode"
|
||||
index="zope.ManageContent"
|
||||
add="zope.ManageContent"
|
||||
/>
|
||||
|
||||
</configure>
|
||||
|
|
|
@ -26,6 +26,7 @@ from zope.cachedescriptors.property import Lazy
|
|||
from zope.app import zapi
|
||||
from zope.app.container.browser.contents import JustContents
|
||||
from zope.app.dublincore.interfaces import ICMFDublinCore
|
||||
from zope.configuration.config import ConfigurationContext
|
||||
from zope.proxy import removeAllProxies
|
||||
from zope.security import canAccess, canWrite
|
||||
from zope.security.proxy import removeSecurityProxy
|
||||
|
@ -104,18 +105,41 @@ class ConfigureBaseView(object):
|
|||
self.context = removeSecurityProxy(context)
|
||||
self.request = request
|
||||
|
||||
@Lazy
|
||||
def loopsRoot(self):
|
||||
return self.context.getLoopsRoot()
|
||||
|
||||
def checkCreateTarget(self):
|
||||
form = self.request.form
|
||||
if 'field.createTarget' in form:
|
||||
if form.get('field.createTarget', False):
|
||||
type = self.request.form.get('field.targetType',
|
||||
'loops.resource.MediaAsset')
|
||||
# TODO: find class (better: factory) from type name
|
||||
factory = ConfigurationContext().resolve(type)
|
||||
uri = self.request.form.get('field.targetUri', None)
|
||||
# TODO: generate uri/__name__ if not given
|
||||
if uri:
|
||||
# TODO: find container
|
||||
self.context.getLoopsRoot()['resources']['ma07'] = MediaAsset()
|
||||
#self.context.loopsRoot['resources']['ma07'] = MediaAsset()
|
||||
path = uri.split('/')
|
||||
containerName = path[-2]
|
||||
name = path[-1]
|
||||
else:
|
||||
containerName = 'resource' in type and 'resources' or 'concepts'
|
||||
viewManagerPath = zapi.getPath(self.context.getViewManager())
|
||||
name = zapi.getPath(self.context)[len(viewManagerPath)+1:]
|
||||
name = name.replace('/', '.')
|
||||
container = self.loopsRoot[containerName]
|
||||
# check for duplicates:
|
||||
num = 1
|
||||
basename = name
|
||||
while name in container:
|
||||
name = '%s-%d' % (basename, num)
|
||||
num += 1
|
||||
# create target:
|
||||
container[name] = factory()
|
||||
target = container[name]
|
||||
# set possibly new targetUri in request for further processing:
|
||||
targetUri = self.loopsRoot.getLoopsUri(target)
|
||||
form['field.targetUri'] = targetUri
|
||||
return target
|
||||
|
||||
|
||||
class ConfigureView(object):
|
||||
""" An editing view for configuring a node, optionally creating
|
||||
|
|
|
@ -65,6 +65,9 @@ class Concept(Contained, Persistent):
|
|||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self).getLoopsRoot()
|
||||
|
||||
def getViewManager(self):
|
||||
return self.getLoopsRoot().getViewManager()
|
||||
|
||||
# concept relations
|
||||
|
||||
def getSubConcepts(self, relationships=None):
|
||||
|
@ -128,3 +131,8 @@ class ConceptManager(BTreeContainer):
|
|||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self)
|
||||
|
||||
def getViewManager(self):
|
||||
return self.getLoopsRoot().getViewManager()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -218,8 +218,10 @@
|
|||
<adapter factory=".view.NodeConfigAdapter"
|
||||
permission="zope.ManageContent" />
|
||||
|
||||
<adapter factory="loops.target.DocumentProxy" />
|
||||
<adapter factory="loops.target.MediaAssetProxy" />
|
||||
<adapter factory="loops.target.DocumentProxy"
|
||||
permission="zope.ManageContent" />
|
||||
<adapter factory="loops.target.MediaAssetProxy"
|
||||
permission="zope.ManageContent" />
|
||||
|
||||
<view factory="loops.view.NodeTraverser"
|
||||
for="loops.interfaces.INode"
|
||||
|
|
|
@ -43,6 +43,10 @@ class ILoopsObject(Interface):
|
|||
""" Return the loops root object.
|
||||
"""
|
||||
|
||||
def getViewManager():
|
||||
""" Return the (default) view manager.
|
||||
"""
|
||||
|
||||
# concept interfaces
|
||||
|
||||
class IConcept(ILoopsObject):
|
||||
|
@ -310,6 +314,10 @@ class ILoops(ILoopsObject, IFolder):
|
|||
""" The top-level object of a loops site.
|
||||
"""
|
||||
contains(IConceptManager, IResourceManager, IViewManager)
|
||||
|
||||
def getLoopsUri(obj):
|
||||
""" Return the relativ path to obj, starting with '.loops/...'.
|
||||
"""
|
||||
|
||||
|
||||
class ILoopsContained(Interface):
|
||||
|
|
|
@ -55,6 +55,9 @@ class Resource(Contained, Persistent):
|
|||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self).getLoopsRoot()
|
||||
|
||||
def getViewManager(self):
|
||||
return self.getLoopsRoot().getViewManager()
|
||||
|
||||
def getClients(self, relationships=None):
|
||||
rels = getRelations(second=self, relationships=relationships)
|
||||
return [r.first for r in rels]
|
||||
|
@ -105,4 +108,8 @@ class ResourceManager(BTreeContainer):
|
|||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self)
|
||||
|
||||
def getViewManager(self):
|
||||
return self.getLoopsRoot().getViewManager()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ from zope.app import zapi
|
|||
from zope.cachedescriptors.property import Lazy
|
||||
from zope.component import adapts
|
||||
from zope.interface import implements
|
||||
from zope.security.proxy import removeSecurityProxy
|
||||
|
||||
from loops.interfaces import IResource, IDocument, IMediaAsset
|
||||
from loops.interfaces import IView
|
||||
|
@ -37,16 +38,17 @@ class ResourceProxy(object):
|
|||
adapts(IView)
|
||||
|
||||
def getTitle(self): return self.target.title
|
||||
def setTitle(self, title): self.title = title
|
||||
def setTitle(self, title): self.target.title = title
|
||||
title = property(getTitle, setTitle)
|
||||
|
||||
def setContentType(self, contentType):
|
||||
self.target._contentType = contentType
|
||||
self.target.contentType = contentType
|
||||
def getContentType(self): return self.target.contentType
|
||||
contentType = property(getContentType, setContentType)
|
||||
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
#self.context = removeSecurityProxy(context)
|
||||
|
||||
@Lazy
|
||||
def target(self):
|
||||
|
|
38
view.py
38
view.py
|
@ -60,7 +60,8 @@ class View(object):
|
|||
if len(rels) == 0:
|
||||
return None
|
||||
if len(rels) > 1:
|
||||
raise ValueError, 'There may be only one target for a View object.'
|
||||
raise ValueError('There may be only one target for a View object: %s - %s'
|
||||
% (zapi.getName(self), `[zapi.getName(r.second) for r in rels]`))
|
||||
return list(rels)[0].second
|
||||
|
||||
def setTarget(self, target):
|
||||
|
@ -72,8 +73,9 @@ class View(object):
|
|||
return
|
||||
else:
|
||||
registry.unregister(oldRel)
|
||||
rel = TargetRelation(self, target)
|
||||
registry.register(rel)
|
||||
if target:
|
||||
rel = TargetRelation(self, target)
|
||||
registry.register(rel)
|
||||
|
||||
target = property(getTarget, setTarget)
|
||||
|
||||
|
@ -85,6 +87,9 @@ class View(object):
|
|||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self).getLoopsRoot()
|
||||
|
||||
def getViewManager(self):
|
||||
return zapi.getParent(self).getViewManager()
|
||||
|
||||
|
||||
class Node(View, OrderedContainer):
|
||||
|
||||
|
@ -141,6 +146,9 @@ class ViewManager(OrderedContainer):
|
|||
def getLoopsRoot(self):
|
||||
return zapi.getParent(self)
|
||||
|
||||
def getViewManager(self):
|
||||
return self
|
||||
|
||||
|
||||
class TargetRelation(DyadicRelation):
|
||||
""" A relation between a view and another object.
|
||||
|
@ -186,24 +194,30 @@ class NodeConfigAdapter(object):
|
|||
@Lazy
|
||||
def loopsRoot(self): return self.context.getLoopsRoot()
|
||||
|
||||
@Lazy
|
||||
def target(self):
|
||||
return self.context.target
|
||||
|
||||
def getTargetUri(self):
|
||||
rootPath = zapi.getPath(self.loopsRoot)
|
||||
if self.context.target is not None:
|
||||
path = zapi.getPath(self.context.target)[len(rootPath):]
|
||||
return '.loops' + path
|
||||
target = self.target
|
||||
if target is not None:
|
||||
return self.loopsRoot.getLoopsUri(target)
|
||||
else:
|
||||
return ''
|
||||
|
||||
def setTargetUri(self, uri):
|
||||
names = uri.split('/')
|
||||
if names[0] == '.loops':
|
||||
path = '/'.join(names[1:])
|
||||
self.context.target = zapi.traverse(self.loopsRoot, path)
|
||||
if uri:
|
||||
names = uri.split('/')
|
||||
if names[0] == '.loops':
|
||||
path = '/'.join(names[1:])
|
||||
self.context.target = zapi.traverse(self.loopsRoot, path)
|
||||
else:
|
||||
self.context.target = None
|
||||
|
||||
targetUri = property(getTargetUri, setTargetUri)
|
||||
|
||||
def getTargetType(self):
|
||||
target = self.context.target
|
||||
target = self.target
|
||||
if target:
|
||||
return '%s.%s' % (target.__module__, target.__class__.__name__)
|
||||
return None
|
||||
|
|
Loading…
Add table
Reference in a new issue