External Methods in Plone
Prerequisite
If it doesn't exist already, you'll need to create a folder to house your external methods and reference that directory in buildout.cfg.
Depending on your Plone installation type, put this either under your [instance]
or [client#]
headings:
zope-conf-additional = extensions ${buildout:directory}/DIRECTORY_NAME
Don't forget to make sure your extensions directory exists.
Stop your Plone instances, and run buildout:
sudo -u plone_buildout bin/buildout
Once your Plone instances are started, External Methods you create will reside in this new folder.
External Method
Create a new Python script in your new DIRECTORY_NAME directory that you created earlier, this example will return the output of the dig command.
import subprocess
def dig(self, domain):
# If you send the form data directly to this method, you can access the request object with:
# self.REQUEST.get('YOUR_ATTRIBUTE')
return subprocess.check_output(['dig', domain])
In your Zope Management Interface create a new External Method and give it a name, then fill in the necessary fields so it can read your previous Python (in this example, each can contain: dig).
Script (Optional)
This step is optional as it depends on how you want to call your External Method, you can just send any form data directly to the External Method but I send it to a script usually for validation etc.
Create a new Script (Python) item in the Zope Management Interface and give it a name, this script will call your External Method, to call it you use context.externalmethod_id:
request = container.REQUEST # contains the form input fields
if not request.domain: # Check if the domain field exists in the request send to the script
context.plone_utils.addPortalMessage("You must enter a domain.", "error") # add a message to appear in portal messages
context.REQUEST.RESPONSE.redirect(context.absolute_url()) # redirect so the above message appears straight away
return context.dig_em(request.domain) # dig_em being the id of the External Method
Page Template
For our form form, create a new Page Template, we can reference the output of the script using structure context/script_id:
<html metal:use-macro="context/main_template/macros/master">
<body metal:fill-slot="main">
<h1>Page Title</h1>
<form action="" method="post">
<input type="text" placeholder="example.com" id="domain" name="domain" tal:attributes="value python:context.REQUEST.get('domain', None)" />
<input type="submit" value="Dig" />
</form>
<pre tal:condition="exists:python:context.REQUEST.domain" tal:content="context/search">result</pre>
</body>
</html>