问题
This question has evolved in a confusing way. Some of its parts though, and specially some answers, might be useful for someone. Therefore I'll let this question unmodified and I'll try to reformulate the question here.
Overriding the template folder_full_view_item.pt
with z3c.jbot
will override the template for all Content Types.
How do I override it only for a single Content Type MyType
in a Product with many types?
Having the following structure:
Folder (layout=folder_full_view)
Document (layout=document_view)
MyType (layout=mytype_view)
The default steps in Plone are:
- The template
folder_full_view.pt
callsfolder_full_view_item.pt
viaitem.getObject().folder_full_view_item()
. - Products.CMFPlone's template
folder_full_view_item.pt
adds different ViewletManagers (abovecontenttitle etc.) and calls the item's layout viause-macro="item_macro"
. - The template of the item (
document_view
,mytype_view
etc.) is included.
What I need is a way to override the template folder_full_view_item.pt
. Calling in step #2 the overridden template folder_full_view_item.pt
for MyType
and Plone's folder_full_view_item.pt
for all other Content Types.
UPDATE
It seems that the template folder_full_view_item.pt
cannot be overriden (without using jbot). The call item.getObject().folder_full_view_item()
in the template folder_full_view.pt
doesn't seems to go through "queryMultiAdapter" neither.
I present here all the steps to reproduce it and confirm that folder_full_view_item
is ignored:
Set the PLONE_HOME
path and remove existing exaple.theme
if necessary:
PLONE_HOME=/path/to/Plone-4.3.2
cd ${PLONE_HOME}/zeocluster/src
rm -rf ${PLONE_HOME}/zeocluster/src/example.theme
sed -i '/example\.theme/d' ${PLONE_HOME}/zeocluster/buildout.cfg
run buildout with develop.cfg
:
sudo -u plone_buildout ${PLONE_HOME}/zeocluster/bin/buildout -c ${PLONE_HOME}/zeocluster/develop.cfg
cd ${PLONE_HOME}/zeocluster/src
rm -rf /home/Plone-4.3.2/zeocluster/src/example.theme
sudo -u plone_buildout ${PLONE_HOME}/zeocluster/bin/paster create \
--no-interactive \
--overwrite \
-o ${PLONE_HOME}/zeocluster/src \
-t plone3_theme example.theme \
expert_mode=all \
namespace_package=example \
package=theme \
skinname='ExampleTheme' \
skinbase='Sunburst Theme' \
empty_styles=False \
include_doc=True \
version=1.0 \
description='An installable theme for Plone 3' \
add_profile=True \
long_description= \
author= \
author_email= \
keywords='web zope plone theme' \
url='http://svn.plone.org/svn/collective/' \
license_name=GPL \
zip_safe=False \
zope2product=True
add example.theme
to buildout:
sed -i '79i\ \ \ \ example.theme' ${PLONE_HOME}/zeocluster/buildout.cfg
sed -i '102i\ \ \ \ src/example.theme' ${PLONE_HOME}/zeocluster/buildout.cfg
register browser:pages
cat << EOF > ${PLONE_HOME}/zeocluster/src/example.theme/example/theme/configure.zcml
<configure
xmlns:browser="http://namespaces.zope.org/browser"
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five"
xmlns:cmf="http://namespaces.zope.org/cmf"
xmlns:i18n="http://namespaces.zope.org/i18n"
i18n_domain="example.theme">
<five:registerPackage package="." initialize=".initialize" />
<include package=".browser" />
<include file="skins.zcml" />
<include file="profiles.zcml" />
<i18n:registerTranslations directory="locales" />
<browser:page
for="*"
name="folder_full_view_item"
template="folder_full_view_item.pt"
layer="example.theme.browser.interfaces.IThemeSpecific"
permission="zope2.View"
/>
<browser:page
for="Products.ATContentTypes.content.folder.ATFolder"
name="folder_full_view"
template="folder_full_view.pt"
layer="example.theme.browser.interfaces.IThemeSpecific"
permission="zope2.View"
/>
<browser:page
for="Products.ATContentTypes.content.document.ATDocument"
name="document_view"
template="document_view.pt"
layer="example.theme.browser.interfaces.IThemeSpecific"
permission="zope2.View"
/>
</configure>
EOF
copy original files (document_view.pt
, folder_full_view.pt
, and folder_full_view_item.pt
) to theme:
cp -f ${PLONE_HOME}/buildout-cache/eggs/Products.CMFPlone-4.3.2-py2.7.egg/Products/CMFPlone/skins/plone_content/document_view.pt \
${PLONE_HOME}/zeocluster/src/example.theme/example/theme/document_view.pt
cp -f ${PLONE_HOME}/buildout-cache/eggs/Products.CMFPlone-4.3.2-py2.7.egg/Products/CMFPlone/skins/plone_content/folder_full_view_item.pt \
${PLONE_HOME}/zeocluster/src/example.theme/example/theme/folder_full_view_item.pt
cp -f ${PLONE_HOME}/buildout-cache/eggs/Products.CMFPlone-4.3.2-py2.7.egg/Products/CMFPlone/skins/plone_content/folder_full_view.pt \
${PLONE_HOME}/zeocluster/src/example.theme/example/theme/folder_full_view.pt
slightly modify overriden templates to recognize them:
sed -i '/<metal:content-core define-macro="content-core">/a overriden template at '${PLONE_HOME}'/zeocluster/src/example.theme/example/theme/document_view.pt' \
${PLONE_HOME}/zeocluster/src/example.theme/example/theme/document_view.pt
sed -i '/<metal:entries fill-slot="entries">/a overriden template at '${PLONE_HOME}'/zeocluster/src/example.theme/example/theme/folder_full_view.pt' \
${PLONE_HOME}/zeocluster/src/example.theme/example/theme/folder_full_view.pt
sed -i '/<div tal:replace="structure provider:plone.abovecontenttitle" \/>/i overriden template at '${PLONE_HOME}'/zeocluster/src/example.theme/example/theme/folder_full_view_item.pt' \
${PLONE_HOME}/zeocluster/src/example.theme/example/theme/folder_full_view_item.pt
chown -R plone_buildout example.theme
run buildout and start plone:
sudo -u plone_buildout ${PLONE_HOME}/zeocluster/bin/buildout -c ${PLONE_HOME}/zeocluster/develop.cfg
${PLONE_HOME}/zeocluster/bin/zeoserver restart
${PLONE_HOME}/zeocluster/bin/client1 fg
If you want to programmatically create test data (e.g. from ipython) then you could do the following:
utils.sync()
plone_site_name = 'Plone'
# delete 'Plone' site if existing
if app.hasObject(plone_site_name): app.manage_delObjects(plone_site_name)
from Products.CMFPlone.factory import addPloneSite
# create 'Plone' site
plone_site = addPloneSite(
app,
plone_site_name,
profile_id=('Products.CMFPlone:plone',),
extension_ids=('plonetheme.classic:default',
'plonetheme.sunburst:default',),
setup_content=False,
)
plone_site = app[plone_site_name]
# install 'plone.app.theming' and 'example.theme'
plone_site.portal_quickinstaller.installProduct('plone.app.theming')
plone_site.portal_quickinstaller.installProduct('example.theme')
# create some content
plone_site.invokeFactory('Document', 'document')
folder_id = plone_site.invokeFactory('Folder', 'folder')
plone_site[folder_id].setLayout('folder_full_view')
plone_site[folder_id].invokeFactory('Document', 'document')
utils.commit()
UPDATE 2
Adding the following as suggested doesn't work either:
define a subclass from zope.interface.Interface:
cat << EOF >> ${PLONE_HOME}/zeocluster/src/example.theme/example/theme/browser/interfaces.py
from zope.interface import Interface
class IMyLayer(Interface):
""" """
EOF
register it as a browser layer:
cat << EOF > ${PLONE_HOME}/zeocluster/src/example.theme/example/theme/profiles/default/browserlayer.xml
<?xml version="1.0"?>
<layers>
<layer name="imylayer" interface="example.theme.browser.interfaces.IMyLayer" />
</layers>
EOF
register the browser:page for this layer:
sed -i 's/layer="example.theme.browser.interfaces.IThemeSpecific"/layer="example.theme.browser.interfaces.IMyLayer"/' \
${PLONE_HOME}/zeocluster/src/example.theme/example/theme/configure.zcml
UPDATE 3
The call item.getObject().folder_full_view_item()
seems not to go through the "usual" layers!
I've tested the following with the example above:
in folder_full_view
substitute the call item.getObject().folder_full_view_item()
with item.getObject().document_view()
modify the original document_view.pt
echo "original document_view" > ${PLONE_HOME}/buildout-cache/eggs/Products.CMFPlone-4.3.2-py2.7.egg/Products/CMFPlone/skins/plone_content/document_view.pt
modify the document_view.pt
in example.theme
echo "overriden document_view" > /home/Plone-4.3.2/zeocluster/src/example.theme/example/theme/document_view.pt
calling the document uses the overriden document_view.pt
curl -s 'http://localhost:8080/Plone/document' | grep "document_view"
overriden document_view
but calling the folder (with a document in it) uses the original document_view.pt
curl -s 'http://localhost:8080/Plone/folder' | grep "document_view"
original document_view
Thus the central questions seem to be:
goes the call item.getObject().template_name()
in a template through the "usual" publishing/layers process?
If not, how to call a template like folder_full_view_item
form folder_full_view
and make it go trough the "usual" publishing/layers process?
Can someone give a hint for which part of zope/plone is responsible for this "publishing/layers process"?
回答1:
Instead of overriding folder_full_view_item.pt
you should rather create your own custom default template for your Content Type MyType
.
回答2:
Try using tal:condition="python:item_type=='MyType'"
and item_type!='MyType'
for different display needs. Hope this helpful.
回答3:
To override this template you will need 2 things: a browser layer and the view that is going to be used in the context of your content type.
First, declare the browser layer:
from zope.interface import Interface
class IMyLayer(Interface):
"""A layer specific for this add-on product.
"""
This browser layer needs to be installed with your content type. Create a browserlayer.xml file with the following:
<?xml version="1.0"?>
<layers>
<layer name="my.type" interface="my.type.interfaces.IMyLayer" />
</layers>
Then, the view will be active when you are in the context of your content type and when your browser layer is active:
from five import grok
class FolderFullViewItem(grok.View):
"""Override folder_full_view_item for MyType.
"""
grok.context(IMyType)
grok.layer(IMyLayer)
grok.name('folder_full_view_item')
grok.template('folder_full_view_item')
grok.require('zope2.View')
On sc.blog we have a similar use case on which we override folder_summary_view and folder_full_view, take a look on it.
Also, don't forget to read the Layers chapter on the Plone Developers Documentation.
回答4:
As the skins-tool seems to be deprecated and probably performance-losses would be involved, I'd rather go with a dedicated browser-view for your custom-contenttype, too, but to answer the question:
You can use collective.editskinswitcher (thanks to M. v. Rees!), without rewriting too much and even getting some nice and easy to configure dev-features along the way (visitors-view, while actually logged-in, via URL-distinction, e.g.).
In this case, we take advantage of the possibility to set the skin-property on a folderish contenttype-object and roughly, these steps should make the deal:
Place the customized
folder_full_view_item.pt
-template in any of your theme's skin-folders.On creation of your contenttype, add an event-listener, which sets the freshly born object's
skin_name
to your theme's skin-name (have a look at c.editskinswitcher for methods and props, the referring HTTP-request is@@switchDefaultSkin?skin_name=YourTheme
, btw).Set another theme-skin as the global default for all other contextes in portal_skins-properties.
来源:https://stackoverflow.com/questions/21464202/how-to-override-template-folder-full-view-item-pt-only-for-a-custom-type