Simple example how to extend Archetype template to add additional button and custom action for it.
This article shows how to solve simple use case. Lets say that we have few content types and we want to add an additional button and action that will be executed after it is pressed. Example presented below is about “edit and publish” button which saves changes and automatically publishes object.
Simple and ugly solution is to change base_edit template for each of those types. But this solution has so many obvious disadvantages that it is not even worth to mention it. We are smart and we use what Archetypes offer. We will use capability that when base_edit is rendered it searches for template _edit. (For content type named Page it will be page_edit.) If it is found basic macros are retrieved from it instead of using default ones from edit_macros. We can redefine all of macros:
We can also redefine slots, that are inside macros, like we’ll do with extra_buttons.
So lets create Page Template page_edit. pt. Inside we will define new macro body which will override standard one. But in reality we will use standard body macro from edit_macros. pt. We will only fill slot extra_buttons.
metal:macro define-macro = “body” > metal:macro use-macro = “here/edit_macros/macros/body” > metal:slot fill-slot = “extra_buttons” > metal:macro use-macro = “here/content_macros/macros/extra_buttons” /> metal:slot > /metal:macro > metal:macro >
As you probably noticed we are using macro extra_buttons from new template content_macros. pt. It is very simple, defines just one button. The most important thing is parameter name which is responsible for action called after submission. It this case script must be called edit_and_publish. py
In order to make our future button to work we must add its action to base_edit. cpt. metadata file. We have to copy it to our skin from Plone skin and add one line at the beginning in actions section.
Python script for action
This Python Script edit_and_publsih. py should be added to skins. It process all fields from form to save data and then change workflow state. After success it redirects to object view with status message. This is of course an example and we can add anything we want here.
## Script (Python) “edit_and_publish” ##title=Edit content ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind state=state ##bind subpath=traverse_subpath ##parameters= ## from Products. CMFCore. utils import getToolByName #Save changes normal way context. processForm() portal_workflow = getToolByName(context, ‘portal_workflow’ , None ) #change workflow if portal_workflow. getInfoFor(context, ‘review_state’ ) != ‘published’ : try : portal_workflow. doActionFor(context, ‘publish’ ) portal_status_message = “Changes saved and document published” except : pass return context. REQUEST. RESPONSE. redirect( “%s? portal_status_message=%s” %( context. absolute_url(),portal_status_message))
New Python script for action
Really nice post. I have exactly the same code in one of my product I wrote some months ago.
Just a note, using portal_status_message is deprecated.
Here is a new Python script:
from Products. CMFCore. utils import getToolByName
from Products. Foobar import FoobarMessageFactory as _
#Save changes normal way
state = context. content_edit_impl(state, id)
context = state. getContext()
portal_workflow = getToolByName(context, ‘portal_workflow’, None)
if portal_workflow. getInfoFor(context, ‘review_state’) != ‘published’:
portal_workflow. doActionFor(context, ‘publish’)
msg = _(u”Changes saved and document published.”)
msg = _(u”Changes saved but document not published.”)
context. plone_utils. addPortalMessage(msg)
And of course in Products/Foobar/__init__.py you have:
from zope. i18nmessageid import MessageFactory
FoobarMessageFactory = MessageFactory(‘foobar’)
from Products. PythonScripts. Utility import allow_module
allow_module(‘Products. Foobar. FoobarMessageFactory’)
Dear ЕЃukasz ЕЃakomy,
thanks a lot for this tutorial, it is very clearly written and understandable 🙂
I followed your instructions very carefully and read over the tutorial uncountable times to make sure I didn’t miss something. The extrabutton shows up but the script won’t be executed.
I am working on a Plone 2.5.2 instance, but that shouldn’t be problem, should it? Or do you have an idea where the problem could be?
I am very grateful for any hint to make this work.
It is difficult to say without being able to see the code and access the system. Is script called at all? You can check it by simply raising an error within script. If it is called then somewhere inside something doesn’t work as it should.
Maybe there is a typo in. metadata file?
There should be no problem with Plone 2.5 although it was originally written for 2.1.