Media assets and documents as target objects for nodes: basically OK

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1043 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2006-01-28 13:09:39 +00:00
parent b02329358a
commit 21b6af48b9
8 changed files with 117 additions and 52 deletions

View file

@ -286,11 +286,6 @@ target may be moved or renamed without any problems.)
>>> 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
>>> nodeConfig.targetType
@ -327,16 +322,33 @@ application uses a subclass that does all the other stuff for form handling.)
>>> isinstance(resources['m1.m11.m111'], Document)
True
It is also possible to edit a target's attributes directly in an
A node object provides the targetSchema of its target:
>>> from loops.interfaces import IDocumentView
>>> from loops.interfaces import IMediaAssetView
>>> IDocumentView.providedBy(m111)
True
>>> IMediaAssetView.providedBy(m111)
False
>>> m111.target = None
>>> IDocumentView.providedBy(m111)
False
>>> m111.target = resources['ma07']
>>> IDocumentView.providedBy(m111)
False
>>> IMediaAssetView.providedBy(m111)
True
It is possible to edit a target's attributes directly in an
edit form provided by the node:
>>> from loops.target import DocumentProxy, MediaAssetProxy
>>> ztapi.provideAdapter(INode, IDocument, DocumentProxy)
>>> ztapi.provideAdapter(INode, IMediaAsset, MediaAssetProxy)
>>> ztapi.provideAdapter(INode, IDocumentView, DocumentProxy)
>>> ztapi.provideAdapter(INode, IMediaAssetView, MediaAssetProxy)
>>> proxy = zapi.getAdapter(m111, IDocument)
>>> proxy = zapi.getAdapter(m111, IDocumentView)
>>> proxy.title = u'Set via proxy'
>>> resources['m1.m11.m111'].title
>>> resources['ma07'].title
u'Set via proxy'
Ordering Nodes

View file

@ -167,7 +167,7 @@
<addform
label="Add Document"
name="AddLoopsDocument.html"
schema="loops.interfaces.IDocument"
schema="loops.interfaces.IDocumentSchema"
fields="title data contentType"
content_factory="loops.resource.Document"
permission="zope.ManageContent" />
@ -184,7 +184,7 @@
<editform
label="Edit Document"
name="edit.html"
schema="loops.interfaces.IDocument"
schema="loops.interfaces.IDocumentSchema"
fields="title data contentType"
for="loops.interfaces.IDocument"
permission="zope.ManageContent"
@ -195,7 +195,7 @@
<addform
label="Add Media Asset"
name="AddLoopsMediaAsset.html"
schema="loops.interfaces.IMediaAsset"
schema="loops.interfaces.IMediaAssetSchema"
fields="title data contentType"
content_factory="loops.resource.MediaAsset"
permission="zope.ManageContent"
@ -212,11 +212,11 @@
<editform
label="Edit Media Asset"
name="edit.html"
schema="loops.interfaces.IMediaAsset"
schema="loops.interfaces.IMediaAssetSchema"
fields="title data contentType"
for="loops.interfaces.IMediaAsset"
permission="zope.ManageContent"
menu="zmi_views" title="Edit"
menu="zmi_views" title="Edit Media Asset"
/>
<!-- suppress the upload menu item: -->
@ -271,8 +271,8 @@
label="Add Node"
name="AddLoopsNode.html"
content_factory="loops.view.Node"
schema="loops.interfaces.INodeConfigSchema"
fields="title description nodeType targetType targetUri createTarget"
schema="loops.interfaces.INode"
fields="title description nodeType body"
class="loops.browser.node.ConfigureView"
permission="zope.ManageContent">
@ -327,20 +327,25 @@
</editform>
<editform
label="Edit Target"
label="Edit Media Asset"
name="edit_target.html"
schema="loops.interfaces.IMediaAsset"
fields="title data contentType"
for="loops.interfaces.INode"
for="loops.interfaces.IMediaAssetView"
permission="zope.ManageContent"
menu="zmi_views" title="Edit Media Asset"
/>
<menuItem
for="loops.interfaces.INode"
menu="zmi_views" action="edit_target.html" title="Edit Target"
filter="context/target"
<editform
label="Edit Document"
name="edit_target.html"
schema="loops.interfaces.IDocument"
fields="title data contentType"
for="loops.interfaces.IDocumentView"
permission="zope.ManageContent"
menu="zmi_views" title="Edit Document"
/>
<page
name="node.html"
for="loops.interfaces.INode"

View file

@ -26,7 +26,8 @@ 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
#import zope.configuration.name
from zope.dottedname.resolve import resolve
from zope.proxy import removeAllProxies
from zope.security import canAccess, canWrite
from zope.security.proxy import removeSecurityProxy
@ -114,7 +115,7 @@ class ConfigureBaseView(object):
if form.get('field.createTarget', False):
type = self.request.form.get('field.targetType',
'loops.resource.MediaAsset')
factory = ConfigurationContext().resolve(type)
factory = resolve(type)
uri = self.request.form.get('field.targetUri', None)
if uri:
path = uri.split('/')

View file

@ -54,6 +54,8 @@ class Concept(Contained, Persistent):
implements(IConcept, IConceptManagerContained)
proxyInterface = IConcept
_title = u''
def getTitle(self): return self._title
def setTitle(self, title): self._title = title

View file

@ -47,9 +47,18 @@ class ILoopsObject(Interface):
""" Return the (default) view manager.
"""
class IPotentialTarget(Interface):
""" For objects that may be used as target objects for view objects.
"""
proxyInterface = Attribute('An interface allowing an object to be '
'used as a target for a view/node (and '
'typically specifying the corresponding schema')
# concept interfaces
class IConcept(ILoopsObject):
class IConcept(ILoopsObject, IPotentialTarget):
""" The concept is the central element of the loops framework.
A concept is related to other concepts, may have resources
@ -115,10 +124,7 @@ class IConceptManagerContained(Interface):
# resource interfaces
class IResource(ILoopsObject):
""" A resource is an atomic information element that is made
available via a view or a concept.
"""
class IResourceSchema(Interface):
title = schema.TextLine(
title=_(u'Title'),
@ -127,13 +133,6 @@ class IResource(ILoopsObject):
missing_value=u'',
required=False)
contentType = schema.BytesLine(
title=_(u'Content Type'),
description=_(u'Content type (format) of the data field'),
default='',
missing_value='',
required=False)
data = schema.Bytes(
title=_(u'Data'),
description=_(u'Resource raw data'),
@ -141,15 +140,26 @@ class IResource(ILoopsObject):
missing_value='',
required=False)
contentType = schema.BytesLine(
title=_(u'Content Type'),
description=_(u'Content type (format) of the data field'),
default='',
missing_value='',
required=False)
class IResource(ILoopsObject, IPotentialTarget):
""" A resource is an atomic information element that is made
available via a view or a concept.
"""
def getClients(relationships=None):
""" Return a sequence of objects that are clients of the resource,
i.e. that have some relation with it.
"""
class IDocument(IResource):
""" A resource containing an editable body.
"""
class IDocumentSchema(IResourceSchema):
data = schema.Text(
title=_(u'Data'),
@ -159,11 +169,17 @@ class IDocument(IResource):
required=False)
class IMediaAsset(IResource, IBaseAsset):
""" A resource containing a (typically binary) file-like content
or an image.
class IDocumentView(IDocumentSchema):
""" Used for accessing a document via a node's target attribute"""
class IDocument(IDocumentSchema, IResource):
""" A resource containing an editable body.
"""
class IMediaAssetSchema(IResourceSchema):
data = schema.Bytes(
title=_(u'Data'),
description=_(u'Media asset file'),
@ -172,6 +188,16 @@ class IMediaAsset(IResource, IBaseAsset):
required=False)
class IMediaAssetView(IMediaAssetSchema):
""" Used for accessing a media asset via a node's target attribute"""
class IMediaAsset(IMediaAssetSchema, IResource, IBaseAsset):
""" A resource containing a (typically binary) file-like content
or an image.
"""
class IResourceManager(ILoopsObject, IContainer):
""" A manager/container for resources.
"""
@ -203,6 +229,7 @@ class IView(ILoopsObject):
target = Attribute('Target object that is referenced by this view')
class IBaseNode(IOrderedContainer):
""" Common abstract base class for different types of nodes
"""
@ -323,4 +350,4 @@ class ILoops(ILoopsObject, IFolder):
class ILoopsContained(Interface):
containers(ILoops)

View file

@ -31,7 +31,9 @@ from persistent import Persistent
from cStringIO import StringIO
from cybertools.relation.registry import getRelations
from interfaces import IResource, IDocument, IMediaAsset
from interfaces import IResource
from interfaces import IDocument, IDocumentSchema, IDocumentView
from interfaces import IMediaAsset, IMediaAssetSchema, IMediaAssetView
from interfaces import IResourceManager, IResourceManagerContained
from interfaces import ILoopsContained
@ -72,6 +74,8 @@ class Document(Resource):
implements(IDocument)
proxyInterface = IDocumentView
_data = u''
def setData(self, data): self._data = data
def getData(self): return self._data
@ -82,6 +86,8 @@ class MediaAsset(Resource, BaseMediaAsset):
implements(IMediaAsset)
proxyInterface = IMediaAssetView
def __init__(self, title=u''):
super(MediaAsset, self).__init__()
self.title = title

View file

@ -29,7 +29,9 @@ 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 IResource
from loops.interfaces import IDocument, IMediaAsset
from loops.interfaces import IDocumentView, IMediaAssetView
from loops.interfaces import IView
@ -47,8 +49,8 @@ class ResourceProxy(object):
contentType = property(getContentType, setContentType)
def __init__(self, context):
self.context = context
#self.context = removeSecurityProxy(context)
#self.context = context
self.context = removeSecurityProxy(context)
@Lazy
def target(self):
@ -58,6 +60,7 @@ class ResourceProxy(object):
class DocumentProxy(ResourceProxy):
implements(IDocument)
adapts(IDocumentView)
def setData(self, data): self.target.data = data
def getData(self): return self.target.data
@ -67,6 +70,7 @@ class DocumentProxy(ResourceProxy):
class MediaAssetProxy(ResourceProxy):
implements(IMediaAsset)
adapts(IMediaAssetView)
def setData(self, data): self.target.data = data
def getData(self): return self.target.data

14
view.py
View file

@ -28,9 +28,10 @@ from zope.app.container.contained import Contained
from zope.app.container.ordered import OrderedContainer
from zope.app.container.traversal import ContainerTraverser, ItemTraverser
from zope.app.container.traversal import ContainerTraversable
from zope.cachedescriptors.property import Lazy
from zope.cachedescriptors.property import Lazy, readproperty
from zope.component import adapts
from zope.interface import implements
from zope.interface import alsoProvides, directlyProvides, directlyProvidedBy
from zope.security.proxy import removeSecurityProxy
from persistent import Persistent
from cybertools.relation import DyadicRelation
@ -73,9 +74,14 @@ class View(object):
return
else:
registry.unregister(oldRel)
oldTargetSchema = oldRel.second.proxyInterface
directlyProvides(self, directlyProvidedBy(self) - oldTargetSchema)
if target:
targetSchema = target.proxyInterface
rel = TargetRelation(self, target)
registry.register(rel)
alsoProvides(self, targetSchema)
target = property(getTarget, setTarget)
@ -194,7 +200,7 @@ class NodeConfigAdapter(object):
@Lazy
def loopsRoot(self): return self.context.getLoopsRoot()
@Lazy
@readproperty
def target(self):
return self.context.target
@ -225,5 +231,7 @@ class NodeConfigAdapter(object):
pass # only used whe a new target object is created
targetType = property(getTargetType, setTargetType)
createTarget = False # not used
def getCreateTarget(self): return False
def setCreateTarget(self, value): pass
createTarget = property(getCreateTarget, setCreateTarget)