Grok is not allowed for Plone core developement. Grok is not recommended for Plone addon development.
Using Grok framework in Plone programming. Grok provides Dont-Repeat-Yourself API to create Zope 3 components easier.
- Using Grok in your package
- Plone 4.3 migration and five.grok dependency
- Grok static media folder
- Creating a viewlet using Grok
- Creating a viewlet manager: Grok way
- More info
Grok is a project to give sane, easy to use, API to Zope 3 systems. It exists as standalone, but Plone compatible port five.grok is available for Plone 3.3 and onwards.
Benefits over using pure Zope 3 APIs
- No ZCML files or XML sit-ups needed (except bootstrapping one configure.zcml file)
- More things are automatic and less explicit hand-written code needed. E.g. template file and view class are automatically matched.
- Less code generation
Grok will automatically scan all .py files in your product and run registration code in them. This way you can use Python decorators and magical classes to perform tasks which before needed to have hand written registration code.
To enable grok'ing for your package:
configure.zcmlmust include the
groknamespace and the
grok:grokdirective. You do not need to put this directive subpackages. This directive scans your package source tree recursively for grok'ed files.
The package must be loaded using
setup.pyauto-include, NOT using a
zcml =section in
buildout.cfg. Otherwise templates are not loaded.
staticfolders to your package root.
- You still need to include subpackages for old-fashioned ZCML configurations.
<configure 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" xmlns:grok="http://namespaces.zope.org/grok" i18n_domain="plonetheme.xxx"> <include package="five.grok" /> <five:registerPackage package="." initialize=".initialize" /> <!-- Grok the package to initialise schema interfaces and content classes --> <grok:grok package="." /> <include package=".browser" /> </configure>
If you are using components from other packages you might also want to add
<includeDependencies package="." />
This makes the
and thus Python code of all modules listed in
install_requires section is loaded before your
module is being processed.
You still need to get
package to your buildout.
Edit your Python egg
file and list
install_requires = ["five.grok", ...],
Re-run buildout. Now buildout should download
for PyPi and activate it for you.
If you are using Plone 4.1 or older you also need Dexterity extends = line pindowns in your buildout. Otherwise you may get Version Conflict errors when running buildout.
Please see Plone 4.2 -> 4.3 Dexterity upgrade guide first.
Plone 4.3 ships with Dexterity.
is a huge dependency with a lot of code of which
maintenance cannot be guaranteed in the future (See grok.zope.org,
discussion). Because Plone community cannot commit to maintain
this code, but we still want to use the best goodies of
grok based development, some compromises was made for
Plone 4.3 regarding grok style forms and directives.
You can include
five.grokas a dependency, as you have done this far, but it is not going to be in Plone default installation in foreseeable future. Please see migration notes.
grok.name()in classes are not supported by Plone 4.3 out of the box
plone.directives.formgoodies distributed to two supported packages:
To make your code Plone 4.3 compatible, grokless way do imports as following:
import z3c.form.form from plone.supermodel import model from plone.autoform import directives as form from plone.autoform.form import AutoExtensibleForm
And you can use them like:
class IChoiceExamples(model.Schema): """ Single choice and multiple choice examples """ form.widget(multiChoiceCheckbox=CheckBoxFieldWidget) multiChoiceCheckbox = zope.schema.List( title=u"Checkbox multiple choices", ...) # Different form base classes are provided: # XXX: Fill in here what you should use with Dexterity content types class ChoiceExamples(AutoExtensibleForm, z3c.form.form.Form): """ """ schema = IChoiceExamples
If you further want to break the dependency with
and get rid of
directives in your classes here are further dependency.
from the dependency list of your egg and remove
ZCML directive in
in all of your package modules.
Declare views and forms using
and map view classes to templates using
Grok migration source example:
class Demos(grok.View): """ Render all demo forms with their widgets in a nice view. Read forms which implements IWidgetDemo marke via @widget_demo class decocator. Build a nice and useful description string for each field in those forms. """ grok.context(ISiteRoot) grok.name("widgets-demo")
<configure 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" xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="plone.app.widgets"> <browser:page name="widgets-demo" for="Products.CMFCore.interfaces.ISiteRoot" class=".demo.Demos" permission="zope2.View" template="widgets-demo.pt" /> </configure>
themselves - this concerns only non-form views
If your view has
method you need to call it manually in
base class doesn't do this.
- def update(self):
- def __call__(self):
- self.update() return self.index() # Or self.render() for grok.CodeView
Learn more about
Since five.grok 1.3.0 this method does not work.
The easiest way to manage static resources is to make use
of the static resource directory feature in five.grok.
Simply add a directory called static in the package and
make sure that the
line appears in configure.zcml.
Example how to include
<configure ... xmlns:grok="http://namespaces.zope.org/grok"> <grok:grok package="." /> </configure>
resource directory in the
package contains a file called
conference.css, it will be accessible on a URL like
http://<server>/site/++resource++example.conference/conference.css. The resource name is the same as the package name
wherein the static directory appears.
Since the release of Plone 4, this (grok) method is simpler.
Example subscription which subscribes a content type to add and edit events:
from five import grok from Products.Archetypes.interfaces import IObjectEditedEvent from Products.Archetypes.interfaces import IObjectInitializedEvent class ORAResearcher(folder.ATFolder, orabase.ORABase, ResearcherMixin): """A Researcher synchronized from ORA. """ implements(IORAResearcher, IResearcher) meta_type = "ORAResearcher" schema = ORAResearcherSchema # Callbacks for both add and edit events @grok.subscribe(ORAResearcher, IObjectEditedEvent) def object_edited(context, event): orabase.object_edited(context, event) @grok.subscribe(ORAResearcher, IObjectInitializedEvent) def object_added(context, event): orabase.object_added(context, event)
Example subscription which subscribes events without context:
# Really old stuff from ZPublisher.interfaces import IPubStart # Modern stuff from five import grok @grok.subscribe(IPubStart) def check_redirect(e): """ Check if we have a custom redirect script in Zope application server root. """
For more information, see:
Grok framework allows you to register a viewlet easily using Python directives.
It is recommended that you use Dexterity ZopeSkel add-on product code skeleton where you add this code.
Then create folder
where you add the related
<tal:extra-head omit-tag="" condition="viewlet/available"> <meta name="something" content="your custom meta"> </tal:extra-head>
Recommended if you want to keep the number of files and lines of XML and Python to a minimum.
An example here for related Python code:
Add dependencies to your
buildout.cfgto include the good known version set.
grokZCML directive to