import os |
import os |
from logging import getLogger |
from logging import getLogger |
|
|
from genshi.filters.transform import Transformer |
from genshi.filters.transform import Transformer |
|
|
from ckan.plugins import implements, SingletonPlugin |
from ckan.plugins import implements, SingletonPlugin |
from ckan.plugins import IConfigurer |
from ckan.plugins import IConfigurer |
from ckan.plugins import IGenshiStreamFilter |
from ckan.plugins import IGenshiStreamFilter |
from ckan.plugins import IRoutes |
from ckan.plugins import IRoutes |
|
|
log = getLogger(__name__) |
log = getLogger(__name__) |
|
|
|
|
class ExampleThemePlugin(SingletonPlugin): |
class ExampleThemePlugin(SingletonPlugin): |
"""This plugin demonstrates how a theme packaged as a CKAN |
"""This plugin demonstrates how a theme packaged as a CKAN |
extension might extend CKAN behaviour. |
extension might extend CKAN behaviour. |
|
|
In this case, we implement three extension interfaces: |
In this case, we implement three extension interfaces: |
|
|
- ``IConfigurer`` allows us to override configuration normally |
- ``IConfigurer`` allows us to override configuration normally |
found in the ``ini``-file. Here we use it to specify the site |
found in the ``ini``-file. Here we use it to specify the site |
title, and to tell CKAN to look in this package for templates |
title, and to tell CKAN to look in this package for templates |
and resources that customise the core look and feel. |
and resources that customise the core look and feel. |
- ``IGenshiStreamFilter`` allows us to filter and transform the |
- ``IGenshiStreamFilter`` allows us to filter and transform the |
HTML stream just before it is rendered. In this case we use |
HTML stream just before it is rendered. In this case we use |
it to rename "frob" to "foobar" |
it to rename "frob" to "foobar" |
- ``IRoutes`` allows us to add new URLs, or override existing |
- ``IRoutes`` allows us to add new URLs, or override existing |
URLs. In this example we use it to override the default |
URLs. In this example we use it to override the default |
``/register`` behaviour with a custom controller |
``/register`` behaviour with a custom controller |
""" |
""" |
implements(IConfigurer, inherit=True) |
implements(IConfigurer, inherit=True) |
implements(IGenshiStreamFilter, inherit=True) |
implements(IGenshiStreamFilter, inherit=True) |
implements(IRoutes, inherit=True) |
implements(IRoutes, inherit=True) |
|
|
def update_config(self, config): |
def update_config(self, config): |
"""This IConfigurer implementation causes CKAN to look in the |
"""This IConfigurer implementation causes CKAN to look in the |
```public``` and ```templates``` directories present in this |
```public``` and ```templates``` directories present in this |
package for any customisations. |
package for any customisations. |
|
|
It also shows how to set the site title here (rather than in |
It also shows how to set the site title here (rather than in |
the main site .ini file), and causes CKAN to use the |
the main site .ini file), and causes CKAN to use the |
customised package form defined in ``package_form.py`` in this |
customised package form defined in ``package_form.py`` in this |
directory. |
directory. |
""" |
""" |
here = os.path.dirname(__file__) |
here = os.path.dirname(__file__) |
rootdir = os.path.dirname(os.path.dirname(here)) |
rootdir = os.path.dirname(os.path.dirname(here)) |
our_public_dir = os.path.join(rootdir, 'ckanext', |
our_public_dir = os.path.join(rootdir, 'ckanext', |
'exampletheme', 'theme', 'public') |
'exampletheme', 'theme', 'public') |
template_dir = os.path.join(rootdir, 'ckanext', |
template_dir = os.path.join(rootdir, 'ckanext', |
'exampletheme', 'theme', |
'exampletheme', 'theme', |
'templates') |
'templates') |
# set our local template and resource overrides |
# set our local template and resource overrides |
config['extra_public_paths'] = ','.join([our_public_dir, |
config['extra_public_paths'] = ','.join([our_public_dir, |
config.get('extra_public_paths', '')]) |
config.get('extra_public_paths', '')]) |
config['extra_template_paths'] = ','.join([template_dir, |
config['extra_template_paths'] = ','.join([template_dir, |
config.get('extra_template_paths', '')]) |
config.get('extra_template_paths', '')]) |
# set the title |
# set the title |
config['ckan.site_title'] = "An example CKAN theme" |
config['ckan.site_title'] = "An example CKAN theme" |
# set the customised package form (see ``setup.py`` for entry point) |
# set the customised package form (see ``setup.py`` for entry point) |
config['package_form'] = "example_form" |
config['package_form'] = "example_form" |
|
|
def filter(self, stream): |
def filter(self, stream): |
"""Conform to IGenshiStreamFilter interface. |
"""Conform to IGenshiStreamFilter interface. |
|
|
This example filter renames 'frob' to 'foobar' (this string is |
This example filter renames 'frob' to 'foobar' (this string is |
found in the custom ``home/index.html`` template provided as |
found in the custom ``home/index.html`` template provided as |
part of the package). |
part of the package). |
""" |
""" |
stream = stream | Transformer('//p[@id="examplething"]/text()')\ |
stream = stream | Transformer('//p[@id="examplething"]/text()')\ |
.substitute(r'frob', r'foobar') |
.substitute(r'frob', r'foobar') |
return stream |
return stream |
|
|
def before_map(self, map): |
def before_map(self, map): |
"""This IRoutes implementation overrides the standard |
"""This IRoutes implementation overrides the standard |
``/user/register`` behaviour with a custom controller. You |
``/user/register`` behaviour with a custom controller. You |
might instead use it to provide a completely new page, for |
might instead use it to provide a completely new page, for |
example. |
example. |
|
|
Note that we have also provided a custom register form |
Note that we have also provided a custom register form |
template at ``theme/templates/user/register.html``. |
template at ``theme/templates/user/register.html``. |
""" |
""" |
map.connect('/user/register', |
# Note that when we set up the route, we must use the form |
|
# that gives it a name (i.e. in this case, 'register'), so it |
|
# works correctly with the url_for helper:: |
|
# h.url_for('register') |
|
map.connect('register', |
|
'/user/register', |
controller='ckanext.exampletheme.controller:CustomUserController', |
controller='ckanext.exampletheme.controller:CustomUserController', |
action='custom_register') |
action='custom_register') |
return map |
return map |
|
|