Can a template in a CMF skin be overridden by a Zope 3 browser:page?
I'm trying to override a view开发者_JAVA百科 provided by a CMF skin layer with a <browser:page ...
having the same name=
attribute. Is this possible in Plone, or can browser views only override other browser views?
(This is a bit late, but what the hell)
CMF Skin layers override browser views. That is why you have to put @@
in front of a browserview's name in an URL, i.e to disambiguate it and make sure that the browserview is called instead of the CMF skin layer template.
So in short, if you put @@
in front, the browserview will override, otherwise not.
i.e:
localhost:8080/Plone/@@myview
overrides:
localhost:8080/Plone/myview
To overcome this, override the template in your CMF skin layer and tal:define
the View
variable to point to your @@myview
. You can then still access the BrowserViews methods from the CMF skin layer template.
By default, the CMF skins mechanism looks in portal_skins before looking up a view. You can change this by customising the IPublishTraverse adapter. It's a bit evil, but this may work (tested in Plone 3 - I'm not 100% sure what the default behaviour is in Plone 4):
from zope.component import adapts, queryMultiAdapter
from zope.publisher.interfaces.browser import IBrowserRequest
from Acquisition import aq_base
from ZPublisher.BaseRequest import DefaultPublishTraverse
from Products.CMFCore.Skinnable import SKINDATA, SkinnableObjectManager
from thread import get_ident
_MARKER = object()
class SkinnableTraverser(DefaultPublishTraverse):
adapts(SkinnableObjectManager, IBrowserRequest)
def publishTraverse(self, request, name):
"""Let the default traverser do its job, but if the thing that was
returned was from a skin layer and there's a view with
the same name, let the view win.
"""
gotten = super(SkinnableTraverser, self).publishTraverse(request, name)
if not name.startswith('_') and not name.startswith('aq_'):
sd = SKINDATA.get(get_ident())
if sd is not None:
ob, skinname, ignore, resolve = sd
if resolve.get(name, None) is aq_base(gotten):
# This was retrieved as a skin resource
# Check if it could've been a view also
view = queryMultiAdapter((self.context, request), name=name)
if view is not None:
return view.__of__(self.context)
return gotten
You need to register this with:
<adapter factory=".skins.SkinnableTraverser" />
Possibly in an overrides.zcml. Another option would be to use a more specific marker interface on the request, e.g. one installed via the browserlayer.xml import step.
Martin
I am not sure about it, but what you can do for fast is to try it with "custom" folder from plone_skins.
You can also try "Alternative" way from http://plone.org/documentation/kb/applying-a-custom-view-to-a-specific-folder
精彩评论