finished registration of macros (for resources, global js calls, etc.) on new view structure with main.pt
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1315 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
173fe3bd0c
commit
f0110c70dc
7 changed files with 125 additions and 45 deletions
|
@ -1,15 +1,68 @@
|
||||||
Browser View Tools
|
Browser View Tools
|
||||||
==================
|
==================
|
||||||
|
|
||||||
We first set up a test and working environment:
|
|
||||||
|
|
||||||
>>> from zope.app import zapi
|
|
||||||
>>> from zope.app.testing import ztapi
|
|
||||||
|
|
||||||
>>> from zope import component, interface
|
>>> from zope import component, interface
|
||||||
>>> from zope.publisher.browser import TestRequest
|
>>> from zope.interface import Interface, implements
|
||||||
>>> from zope.publisher.interfaces.browser import IBrowserRequest
|
>>> from zope.publisher.interfaces.browser import IBrowserRequest
|
||||||
|
|
||||||
|
The Generic View class
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
GenericView is intended as the base class for application-specific views.
|
||||||
|
The GenericView class itself provides only basic functionality, so you
|
||||||
|
will have to subclass it. (An example can be found in loops.browser - see
|
||||||
|
the common and node modules there.)
|
||||||
|
|
||||||
|
Let's start with a dummy content object and create a view on it:
|
||||||
|
|
||||||
|
>>> class SomeObject(object):
|
||||||
|
... implements(Interface)
|
||||||
|
>>> obj = SomeObject()
|
||||||
|
|
||||||
|
>>> from cybertools.browser.view import GenericView
|
||||||
|
>>> class View(GenericView): pass
|
||||||
|
|
||||||
|
>>> from zope.publisher.browser import TestRequest
|
||||||
|
>>> request = TestRequest()
|
||||||
|
>>> view = View(obj, request)
|
||||||
|
|
||||||
|
Via the `template` and `macro` attributes one may control the presentation of
|
||||||
|
the view - in fact the rendering of a certain content object is achieved
|
||||||
|
by providing an appropriate macro for its view.
|
||||||
|
|
||||||
|
The view also may provide a special skin and a menu.
|
||||||
|
|
||||||
|
All these attributes default to None:
|
||||||
|
|
||||||
|
>>> view.template is None
|
||||||
|
True
|
||||||
|
>>> view.macro is None
|
||||||
|
True
|
||||||
|
>>> view.skin is None
|
||||||
|
True
|
||||||
|
>>> view.menu is None
|
||||||
|
True
|
||||||
|
|
||||||
|
The `item` attribute may be used to delegate to another view; it defaults to
|
||||||
|
self:
|
||||||
|
|
||||||
|
>>> view.item is view
|
||||||
|
True
|
||||||
|
|
||||||
|
There is a method for setting the skin that will be called when the controller
|
||||||
|
attribute is set, see below:
|
||||||
|
|
||||||
|
>>> view.setSkin(None)
|
||||||
|
|
||||||
|
When the view is called, the standard main template (main.pt) is rendered;
|
||||||
|
this template in turn calls the view's pageBody() method to render the
|
||||||
|
body.
|
||||||
|
|
||||||
|
This pageBody() method returns the rendered body by accessing another view
|
||||||
|
(default: BodyTemplateView) that provides a corresponding template in its
|
||||||
|
bodyTemplate attribute.
|
||||||
|
|
||||||
|
|
||||||
The View Controller
|
The View Controller
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
@ -24,18 +77,6 @@ because this already provides some predefined stuff:
|
||||||
|
|
||||||
>>> from cybertools.browser.liquid.controller import Controller
|
>>> from cybertools.browser.liquid.controller import Controller
|
||||||
|
|
||||||
Before creating a controller we have to set up a context object and
|
|
||||||
a view:
|
|
||||||
|
|
||||||
>>> class SomeObject(object): pass
|
|
||||||
>>> obj = SomeObject()
|
|
||||||
>>> from cybertools.browser.view import GenericView
|
|
||||||
>>> class View(GenericView):
|
|
||||||
... pass
|
|
||||||
>>> from zope.publisher.browser import TestRequest
|
|
||||||
>>> request = TestRequest()
|
|
||||||
>>> view = View(obj, request)
|
|
||||||
|
|
||||||
>>> controller = Controller(view, request)
|
>>> controller = Controller(view, request)
|
||||||
>>> controller.view is view
|
>>> controller.view is view
|
||||||
True
|
True
|
||||||
|
@ -72,7 +113,7 @@ controller object to get an updated setting:
|
||||||
>>> controller.resourceBase
|
>>> controller.resourceBase
|
||||||
'http://127.0.0.1/++skin++dummy/@@/'
|
'http://127.0.0.1/++skin++dummy/@@/'
|
||||||
|
|
||||||
The controller may be used as a provider for content elements using
|
The controller may be used as a provider for HTML elements using
|
||||||
ZPT macros:
|
ZPT macros:
|
||||||
|
|
||||||
>>> cssMacros = controller.macros['css']
|
>>> cssMacros = controller.macros['css']
|
||||||
|
@ -87,15 +128,34 @@ Calling a macro provided by Controller.macros[] returns the real ZPT macro:
|
||||||
>>> m1()
|
>>> m1()
|
||||||
[...base_macros.pt...css...]
|
[...base_macros.pt...css...]
|
||||||
|
|
||||||
The pre-set collection of macros for a certain slot may be extended:
|
The pre-set collection of macros for a certain slot may be extended
|
||||||
|
(this may be done by overriding the view's setupController() method, e.g.):
|
||||||
|
|
||||||
>>> controller.macros.register('css', resourceName='node.css', media='all')
|
>>> controller.macros.register('css', 'node.css', resourceName='node.css', media='all')
|
||||||
>>> len(controller.macros['css'])
|
>>> len(controller.macros['css'])
|
||||||
5
|
5
|
||||||
>>> m5 = cssMacros[4]
|
>>> m5 = cssMacros[4]
|
||||||
>>> print m5.name, m5.media, m5.resourceName
|
>>> print m5.name, m5.media, m5.resourceName
|
||||||
css all node.css
|
css all node.css
|
||||||
|
|
||||||
|
If an identifier is given (the second parameter) a certain macro is only
|
||||||
|
registered once; note: the first setting will not be overridden!
|
||||||
|
|
||||||
|
>>> controller.macros.register('css', 'node.css', resourceName='node.css')
|
||||||
|
>>> len(controller.macros['css'])
|
||||||
|
5
|
||||||
|
|
||||||
|
We can also access slots that are not predefined:
|
||||||
|
|
||||||
|
>>> controller.macros['js.execute']
|
||||||
|
[]
|
||||||
|
|
||||||
|
>>> jsCall = 'dojo.require("dojo.widget.Editor")'
|
||||||
|
>>> controller.macros.register('js-execute', jsCall, jsCall=jsCall)
|
||||||
|
>>> dojoCall = controller.macros['js-execute'][0]
|
||||||
|
>>> dojoCall()
|
||||||
|
[...base_macros.pt...macro/jsCall...]
|
||||||
|
|
||||||
|
|
||||||
The View Configurator
|
The View Configurator
|
||||||
---------------------
|
---------------------
|
||||||
|
|
|
@ -23,3 +23,8 @@
|
||||||
</script>
|
</script>
|
||||||
</metal:js>
|
</metal:js>
|
||||||
|
|
||||||
|
|
||||||
|
<metal:js define-macro="js-execute">
|
||||||
|
<script tal:content="macro/jsCall"></script>
|
||||||
|
</metal:js>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
<page for="*"
|
<page for="*"
|
||||||
name="body.html"
|
name="body.html"
|
||||||
class="cybertools.browser.view.GenericView"
|
class="cybertools.browser.view.BodyTemplateView"
|
||||||
permission="zope.View"/>
|
permission="zope.View"/>
|
||||||
|
|
||||||
<page name="controller"
|
<page name="controller"
|
||||||
|
|
|
@ -69,12 +69,10 @@ class Macros(dict):
|
||||||
|
|
||||||
def __init__(self, controller):
|
def __init__(self, controller):
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self['css'] = []
|
|
||||||
self['js'] = []
|
|
||||||
self.identifiers = set()
|
self.identifiers = set()
|
||||||
|
|
||||||
def register(self, slot, template=None, name=None, position=None,
|
def register(self, slot, identifier=None, template=None, name=None,
|
||||||
identifier=None, **kw):
|
position=None, **kw):
|
||||||
if identifier:
|
if identifier:
|
||||||
# make sure a certain resource is only registered once
|
# make sure a certain resource is only registered once
|
||||||
if identifier in self.identifiers:
|
if identifier in self.identifiers:
|
||||||
|
@ -85,12 +83,15 @@ class Macros(dict):
|
||||||
if name is None:
|
if name is None:
|
||||||
name = slot
|
name = slot
|
||||||
macro = Macro(template, name, **kw)
|
macro = Macro(template, name, **kw)
|
||||||
if slot not in self:
|
entry = self.setdefault(slot, [])
|
||||||
self[slot] = []
|
|
||||||
if position is None:
|
if position is None:
|
||||||
self[slot].append(macro)
|
entry.append(macro)
|
||||||
else:
|
else:
|
||||||
self[slot].insert(position, macro)
|
entry.insert(position, macro)
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.get(key, [])
|
||||||
|
|
||||||
|
|
||||||
class Macro(object):
|
class Macro(object):
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,12 @@ class Controller(BaseController):
|
||||||
macros = self.macros
|
macros = self.macros
|
||||||
params = [('zope3_tablelayout.css', 'all'),
|
params = [('zope3_tablelayout.css', 'all'),
|
||||||
('base.css', 'screen'),
|
('base.css', 'screen'),
|
||||||
('custom.css', 'all'), ('print.css', 'print')]
|
('custom.css', 'all'),
|
||||||
|
('print.css', 'print')]
|
||||||
for param in params:
|
for param in params:
|
||||||
macros.register('css', resourceName=param[0], media=param[1])
|
macros.register('css', identifier=param[0],
|
||||||
|
resourceName=param[0], media=param[1])
|
||||||
|
|
||||||
def setupJs(self):
|
def setupJs(self):
|
||||||
return
|
return
|
||||||
#self.macros['js'] = []
|
#self.macros.register('js', resourceName='zope3.js')
|
||||||
self.macros.register('js', resourceName='zope3.js')
|
|
||||||
|
|
|
@ -20,11 +20,15 @@
|
||||||
<metal:js use-macro="macro" />
|
<metal:js use-macro="macro" />
|
||||||
</tal:js>
|
</tal:js>
|
||||||
|
|
||||||
|
<tal:js repeat="macro controller/macros/js-execute">
|
||||||
|
<metal:js use-macro="macro" />
|
||||||
|
</tal:js>
|
||||||
|
|
||||||
<link rel="icon" type="image/png"
|
<link rel="icon" type="image/png"
|
||||||
tal:attributes="href string:${resourceBase}favicon.png" />
|
tal:attributes="href string:${resourceBase}favicon.png" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body tal:content="structure body"/>
|
<body tal:content="structure body" />
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
</metal:block>
|
</metal:block>
|
||||||
|
|
|
@ -29,18 +29,27 @@ from zope.publisher.interfaces.browser import ISkin
|
||||||
from zope.app.pagetemplate import ViewPageTemplateFile
|
from zope.app.pagetemplate import ViewPageTemplateFile
|
||||||
|
|
||||||
|
|
||||||
|
mainTemplate = ViewPageTemplateFile('main.pt')
|
||||||
|
|
||||||
|
|
||||||
class UnboundTemplateFile(ViewPageTemplateFile):
|
class UnboundTemplateFile(ViewPageTemplateFile):
|
||||||
|
|
||||||
def __get__(self, instance, type):
|
def __get__(self, instance, type):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
class GenericView(object):
|
class BodyTemplateView(object):
|
||||||
|
""" Dummy view used for providing a body template.
|
||||||
|
"""
|
||||||
|
|
||||||
index = ViewPageTemplateFile('main.pt')
|
|
||||||
bodyTemplate = UnboundTemplateFile('liquid/body.pt')
|
bodyTemplate = UnboundTemplateFile('liquid/body.pt')
|
||||||
|
|
||||||
menu = macro = skin = None
|
|
||||||
|
class GenericView(object):
|
||||||
|
|
||||||
|
index = mainTemplate
|
||||||
|
|
||||||
|
template = macro = menu = skin = None
|
||||||
|
|
||||||
def setController(self, controller):
|
def setController(self, controller):
|
||||||
# make the (one and only controller) available via the request
|
# make the (one and only controller) available via the request
|
||||||
|
@ -66,10 +75,14 @@ class GenericView(object):
|
||||||
def setupController(self):
|
def setupController(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def item(self):
|
||||||
|
return self
|
||||||
|
|
||||||
def pageBody(self):
|
def pageBody(self):
|
||||||
template = component.getMultiAdapter((self.context, self.request),
|
bodyTemplate = component.getMultiAdapter((self.context, self.request),
|
||||||
name='body.html').bodyTemplate
|
name='body.html').bodyTemplate
|
||||||
return template(self)
|
return bodyTemplate(self)
|
||||||
|
|
||||||
def setSkin(self, skinName):
|
def setSkin(self, skinName):
|
||||||
skin = None
|
skin = None
|
||||||
|
@ -79,8 +92,4 @@ class GenericView(object):
|
||||||
applySkin(self.request, skin)
|
applySkin(self.request, skin)
|
||||||
self.skin = skin
|
self.skin = skin
|
||||||
|
|
||||||
@Lazy
|
|
||||||
def item(self):
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue