Как переопределить шаблон folder_full_view_item.pt только для пользовательского типа?

Этот вопрос развивался запутанным образом. Однако некоторые из его частей, и особенно некоторые ответы, могут быть кому-то полезны. Поэтому я оставлю этот вопрос без изменений и попытаюсь переформулировать вопрос здесь.


Переопределение шаблона folder_full_view_item.pt с помощью z3c.jbot приведет к переопределению шаблона для всех типов контента. Как переопределить его только для одного типа контента MyType в продукте со многими типами?

Имея следующую структуру:

Folder (layout=folder_full_view)
    Document (layout=document_view)
    MyType (layout=mytype_view)

Шаги по умолчанию в Plone:

  1. Шаблон folder_full_view.pt вызывает folder_full_view_item.pt через item.getObject().folder_full_view_item().
  2. Шаблон Products.CMFPlone folder_full_view_item.pt добавляет различные ViewletManagers (выше contenttitle и т. д.) и вызывает макет элемента через use-macro="item_macro".
  3. Шаблон элемента (document_view, mytype_view и т.д.) включен.

Мне нужен способ переопределить шаблон folder_full_view_item.pt. Вызов на шаге 2 переопределенного шаблона folder_full_view_item.pt для MyType и шаблона folder_full_view_item.pt Plone для всех остальных типов контента.

ОБНОВЛЕНИЕ

Кажется, что шаблон folder_full_view_item.pt нельзя переопределить (без использования jbot). Вызов item.getObject().folder_full_view_item() в шаблоне folder_full_view.pt, похоже, также не проходит через "queryMultiAdapter".

Я представляю здесь все шаги по его воспроизведению и подтверждаю, что folder_full_view_item игнорируется:

Установите путь PLONE_HOME и при необходимости удалите существующий exaple.theme:

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

запустить сборку с 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

добавить example.theme в сборку:

sed -i '79i\ \ \ \ example.theme' ${PLONE_HOME}/zeocluster/buildout.cfg
sed -i '102i\ \ \ \ src/example.theme' ${PLONE_HOME}/zeocluster/buildout.cfg

зарегистрироваться 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

скопируйте исходные файлы (document_view.pt, folder_full_view.pt и 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/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

слегка изменить переопределенные шаблоны, чтобы распознать их:

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

запустите buildout и запустите 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

Если вы хотите программно создать тестовые данные (например, из ipython), вы можете сделать следующее:

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()

ОБНОВЛЕНИЕ 2

Добавление следующего, как было предложено, также не работает:

определить подкласс из 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

зарегистрируйте его как слой браузера:

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

зарегистрируйте браузер: страницу для этого слоя:

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

ОБНОВЛЕНИЕ 3

Вызов item.getObject().folder_full_view_item() похоже не проходит через "обычные" слои!

Я проверил следующее на приведенном выше примере:

в folder_full_view замените вызов item.getObject().folder_full_view_item() на item.getObject().document_view()

изменить оригинал 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

изменить document_view.pt в example.theme

echo "overriden document_view" > /home/Plone-4.3.2/zeocluster/src/example.theme/example/theme/document_view.pt

вызов документа использует переопределенный document_view.pt

curl -s 'http://localhost:8080/Plone/document' | grep "document_view"
overriden document_view

но при вызове папки (с документом в ней) используется исходный document_view.pt

curl -s 'http://localhost:8080/Plone/folder' | grep "document_view"
original document_view

Таким образом, центральными вопросами, по-видимому, являются:

идет вызов item.getObject().template_name() в шаблоне через «обычный» процесс публикации/слоев?

Если нет, то как вызвать такой шаблон, как folder_full_view_item form folder_full_view, и заставить его пройти через «обычный» процесс публикации/слоев?

Кто-нибудь может подсказать, какая часть zope/plone отвечает за этот "процесс публикации/слоев"?


person wolfrevo    schedule 30.01.2014    source источник


Ответы (4)


Вместо переопределения folder_full_view_item.pt лучше создать свой собственный шаблон по умолчанию для вашего типа контента MyType.

person nachtigall    schedule 30.01.2014
comment
на самом деле мне нужно переопределить folder_full_view_item. Я хочу, чтобы MyType показывал свой собственный вид/шаблон во вложенной папке, в которой выбран макет folder_full_view. Folder_full_view вложенной папки вызывает item.getObject().folder_full_view_item(), который, в свою очередь, вызывает шаблон MyType. folder_full_view_item не только вызывает шаблон MyType, но и добавляет некоторые дополнительные элементы, которые мне не нужны. - person wolfrevo; 31.01.2014

Попробуйте использовать tal:condition="python:item_type=='MyType'" и item_type!='MyType' для разных потребностей отображения. Надеюсь, это полезно.

person marr    schedule 31.01.2014
comment
Я действительно хочу переопределить folder_full_view_item.pt. Пожалуйста, внимательно прочитайте вопрос. - person wolfrevo; 31.01.2014

Чтобы переопределить этот шаблон, вам понадобятся две вещи: слой браузера и представление, которое будет использоваться в контексте вашего типа контента.

Сначала объявите слой браузера:

from zope.interface import Interface

class IMyLayer(Interface):
    """A layer specific for this add-on product.
    """

Этот слой браузера должен быть установлен с вашим типом контента. Создайте файл browserlayer.xml со следующим:

<?xml version="1.0"?>
<layers>
  <layer name="my.type" interface="my.type.interfaces.IMyLayer" />
</layers>

Затем представление будет активным, когда вы находитесь в контексте вашего типа контента и когда активен ваш слой браузера:

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')

На sc.blog у нас есть аналогичный вариант использования, в котором мы переопределяем folder_summary_view и folder_full_view, взгляните на него.

Кроме того, не забудьте прочитать главу Слои в документации разработчиков Plone.

person hvelarde    schedule 31.01.2014
comment
Я действительно хочу переопределить folder_full_view_item.pt, а не folder_full_view.pt. В упомянутом вами примере sc.blog вы просто переопределяете folder_full_view.pt, который вызывает folder_full_view_item.pt Plone. Я знаю, что могу перезаписать folder_full_view.pt вместо MyType и вызвать другой шаблон вместо folder_full_view_item.pt, но это не то, о чем я прошу. Пожалуйста, внимательно прочитайте мой вопрос. - person wolfrevo; 31.01.2014
comment
если вы внимательно прочитаете мой ответ, вы заметите, что grok.context(IMyType) выполняет свою работу. - person hvelarde; 27.03.2014
comment
не могли бы вы развернуть свой ответ? Наш проект беспроигрышный - person wolfrevo; 27.03.2014
comment
Кажется, что template folder_full_view_item.pt нельзя переопределить (без использования jbot!). Вызов item.getObject().folder_full_view_item() в шаблоне folder_full_view.pt даже не кажется тем случаем, что он проходит через queryMultiAdapter. Смотрите обновление моего вопроса. - person wolfrevo; 16.05.2014
comment
Гектор, ваш ответ применим ко всем другим шаблонам, которые должны быть переопределены. Но, к сожалению, это не относится к шаблону folder_full_view_item.pt. Или я неправильно понял проблему со всеми слоями? - person wolfrevo; 19.05.2014
comment
используйте не слой IThemeSpecific, а простой интерфейс маркера. - person hvelarde; 19.05.2014
comment
не могли бы вы предложить конкретную строку кода? Я часами читал загадочные подсказки и переходил по неработающим ссылкам в документации Plone. Я также внимательно прочитал ваш ответ выше и изучил ваш код на sc.blog. Очевидно, без какого-либо успеха. Что я не понимаю? Я был бы очень признателен, если бы вы могли дать мне четкий ответ, который работает с примером, предложенным в моем вопросе выше. - person wolfrevo; 20.05.2014
comment
Извините, но я не могу вам помочь прямо сейчас; Я очень занят. - person hvelarde; 20.05.2014
comment
Я использовал (как я понимаю) простой интерфейс маркера. См. выше. К сожалению, это тоже не работает. Смотрите мое обновление 2 - person wolfrevo; 20.05.2014
comment
Либо я вообще этого не понимаю, либо вызов item.getObject().folder_full_view_item() определенно не ищет слои, как обычно, и поэтому его нельзя переопределить. Смотрите мое обновление 3 - person wolfrevo; 20.05.2014

Поскольку инструмент скинов, похоже, устарел и, вероятно, это приведет к потерям производительности, я бы предпочел также использовать выделенное представление браузера для вашего пользовательского типа контента, но чтобы ответить на вопрос:

Вы можете использовать collective.editskinswitcher (спасибо M. v. Rees!), не переписывая слишком много и даже получить некоторые приятные и простые в настройке функции разработчика по пути (просмотр посетителей, когда они фактически вошли в систему, например, через URL-различение).

В этом случае мы воспользуемся возможностью установить свойство skin для папочного объекта contenttype, и, грубо говоря, эти шаги должны решить проблему:

  • Поместите настроенный шаблон folder_full_view_item.pt в любую из папок оформления вашей темы.

  • При создании вашего типа контента добавьте прослушиватель событий, который устанавливает только что созданный объект skin_name на имя скина вашей темы (посмотрите на c.editskinswitcher для методов и реквизитов, ссылающийся HTTP-запрос @@switchDefaultSkin?skin_name=YourTheme, кстати).

  • Установите другой тематический скин в качестве глобального по умолчанию для всех других контекстов в portal_skins-properties.

person Ida    schedule 20.05.2014
comment
Большое спасибо за ответ! Это именно то, что мы используем сейчас: сочетание тем/скинов, которые мы переключаем с помощью collective.editskinswitcher. Действительно, спасибо Маурицу! Но, помимо того, что это жонглирование и борьба с библиотеками (и документацией!) иногда становится настоящим лавашом, меня на самом деле и действительно очень интересует ответ на мои вопросы: (1) можно или нельзя переопределить folder_full_view_item.pt как большинство людей (опрометчиво) предлагают? и (2) есть ли другой способ вызвать этот шаблон, кроме как через item.getObject().folder_full_view_item()? - person wolfrevo; 21.05.2014
comment
С другой стороны, я был бы очень признателен за четкое заявление от разработчиков plone о том, какие библиотеки/инструменты устарели, устарели, старомодны и т.д. и т.п.? Но на самом деле этот форум не место для жалоб на это ;-) Даже если я очень ценю ваши усилия @ida-ebkes, это не дает ответа на мой вопрос. - person wolfrevo; 21.05.2014
comment
Квест превратился в роман (также известный как tl;dr) и к настоящему времени поднялся на несколько пунктов. Относительно (1) вашего комментария: на него уже ответили многими способами, не стесняйтесь выражать свою признательность голосами (я так и сделал). По поводу (2): Всегда есть способ ;) Но, может быть, вы хотите открыть новый квест с этой конкретной точкой. О разглагольствованиях во втором комментарии: Skins-tool определенно считается устаревшим, но есть кое-что, что нужно сделать, прежде чем придет время, наконец, прощаться. Вероятно, это следует лучше задокументировать и обсудить, как вы предлагаете, что поднимает следующий квест: - person Ida; 21.05.2014
comment
Где обсудить? Традиционно это происходит в списках рассылки, затем SO был включен в качестве опции поддержки, и теперь у нас есть community.plone.org, но официального перехода пока нет. Итак, я переспросил здесь: plone.293351.n2.nabble.com/ о текущем состоянии каналов связи. - person Ida; 21.05.2014
comment
Подводя итоги этого квеста: нет, вы не можете заставить скин-шаблон вести себя точно так же, как представление браузера, очевидно. Однако ваш вариант использования может быть решен различными гораздо лучшими способами. - person Ida; 21.05.2014
comment
К сожалению, на мой вопрос до сих пор нет ответа. Даже если есть много обходных путей, я просто хочу знать, почему folder_full_view_item.pt нельзя (!) переопределить, а folder_full_view.pt можно (!) переопределить? и (2) есть ли способ заменить вызов item.getObject().folder_full_view_item() чем-то другим, вызывающим folder_full_view_item.pt, заставив его пройти через процесс публикации? - person wolfrevo; 21.05.2014
comment
Вы продолжаете повторять, что folder_full_view_item.pt не может быть переопределено, что неверно. Дополнительный запрос был сделать это только для аналога: был дан ответ, и это был забавный вызов в сочетании с олдскульным шаблоном, кстати, спасибо. Совершенно другой квест - это вариант использования, чтобы определить, какой вид / шаблон элемента должен отображаться внутри folder_full_view.pt, который на самом деле является соответствующим шаблоном, который нужно настроить. Из них различаются tal-условия и указывают на желаемый специальный вид/шаблон (см. ответ Марра). Я бы так сделал по крайней мере. - person Ida; 21.05.2014
comment
Пожалуйста, внимательно прочитайте мой пример (я предложил весь код!) и будьте так любезны опровергнуть утверждение, что folder_full_view_item.pt не может быть переопределен так же, как folder_full_view.pt (см. configure.zcml). Я был бы очень признателен, если бы вы показали, где я не прав. Я думаю, я являюсь. Но я действительно не вижу, где и как. Пожалуйста, предложите демонстрацию с воспроизводимым кодом, а не просто заявляйте, что это неправда. Я предложил все шаги для воспроизведения моего примера. На самом деле это не роман. - person wolfrevo; 21.05.2014
comment
Например, ваш квест начинается с переопределения шаблона folder_full_view_item.pt с помощью z3c.jbot, который переопределит шаблон для всех типов контента, если вы подтверждаете, что уже переопределили его. Позже вы заявляете, что не хотите использовать jbot, который изменяет квест, и так далее, это то, что я имею в виду с романом, это много вопросов в одном и трудно понять, и, честно говоря, я не читал все это, кроме странный подход, отказывающий в настройке folder_full_view.pt вместо folder_full_view_item.pt и предоставляющий специальный шаблон, для которого реальное требование кричит. - person Ida; 22.05.2014
comment
Ты совершенно прав. Этот вопрос вырос в своего рода монстра. Я переформулировал этот вопрос: stackoverflow.com/q/23809810/1659599. Я надеюсь, что новый вопрос более понятен. @IdaEbkes: Спасибо за ваши предложения. - person wolfrevo; 22.05.2014