Source code for plone.tiles.tile
from zope.interface import implements
from zope.component import queryMultiAdapter
from zope.publisher.browser import BrowserView
from zope.traversing.browser.absoluteurl import absoluteURL
from plone.tiles.interfaces import ITile, IPersistentTile
from plone.tiles.interfaces import ITileDataManager
[docs]class Tile(BrowserView):
"""Basic implementation of a transient tile. Subclasses should override
__call__ or set an 'index' variable to point to a view page template file.
The tile is basically a browser view, with the following enhancements:
* The attribute `data` can be used to read the tile data, as returned by
`ITileDataManager(tile).get()`. This value is cached when it is first
read.
* The attribute `url` can be used to obtain the tile's URL, including the
id specifier and any data associated with a transient tile. Again, the
return value is cached after the first access.
* The class implements __getitem__() to set the tile id from the traversal
sub-path, as well as to allow views to be looked up. This is what allows
a URL like `http://.../@@example.tile/foo` to result in a tile with id
`foo`.
"""
implements(ITile)
__cachedData = None
__cachedURL = None
id = None
def __getitem__(self, name):
# If we haven't set the id yet, do that first
if self.id is None:
self.id = name
# This is pretty stupid, but it's required to keep the ZPublisher
# happy in Zope 2. It doesn't normally check for docstrings on
# views, but it does check for them on sub-objects obtained via
# __getitem__.
if self.__doc__ is None:
self.__doc__ = "For Zope 2, to keep the ZPublisher happy"
return self
# Also allow views on tiles even without @@.
viewName = name
if viewName.startswith('@@'):
viewName = name[2:]
view = queryMultiAdapter((self, self.request), name=viewName)
if view is not None:
view.__parent__ = self
view.__name__ = viewName
return view
raise KeyError(name)
[docs] def browserDefault(self, request):
"""By default, tiles render themselves with no browser-default view
"""
return self, ()
[docs] def publishTraverse(self, request, name):
"""Ensure that publish-traversal uses the same semantics as
__getitem__.
"""
return self[name]
def __call__(self, *args, **kwargs):
if not hasattr(self, 'index'):
raise NotImplemented(u"Override __call__ or set a class " + \
"variable 'index' to point to a view page template file")
if self.id is not None:
self.request.response.setHeader('X-Tile-Url', self.url)
return self.index(*args, **kwargs)
@property
[docs] def data(self):
if self.__cachedData is None:
reader = ITileDataManager(self)
self.__cachedData = reader.get()
return self.__cachedData
@property
[docs] def url(self):
return absoluteURL(self, self.request)
[docs]class PersistentTile(Tile):
"""Base class for persistent tiles. Identical to `Tile`, except that the
data dict is never serialized with the URL.
"""
implements(IPersistentTile)