How to override template “folder_full_view_item.pt” only for a Custom Type?

百般思念 提交于 2020-01-13 14:55:33

问题


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:

  1. The template folder_full_view.pt calls folder_full_view_item.pt via item.getObject().folder_full_view_item().
  2. Products.CMFPlone's template folder_full_view_item.pt adds different ViewletManagers (abovecontenttitle etc.) and calls the item's layout via use-macro="item_macro".
  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!