Search code examples
ckan

How to add a menu item to CKAN's naivigation menu?


I want to make the functionality of a custom extension available via a menu item in the CKAN's main navigation menu. Not sure how I can add this new menu item from my extension code. Any help would be appreciated.

Thanks, PK


Solution

  • If you want to take advantage of CKAN's main navigation menu, it gets a little tricky. (We just had to figure this out. Not sure if we did it the right way, but we did get it to work with CKAN 2.2):

    First, you need the additional content in your extension path somewhere. Assuming it's at my_extension/amazing.html, you want to add the following to the my_extension/templates/header.html file (in your custom extension):

    {% ckan_extends %}
    
    {% block header_site_navigation_tabs %}
      {{ h.build_nav_main(
        ('search', _('Datasets')),
        ('organizations_index', _('Organizations')),
        ('group_index', _('Groups')),
        ('about', _('About')),
        ('amazing', _('Amazing Extension'))
      ) }}
    {% endblock %}
    

    This will cause a server error, since "amazing" hasn't been registered in pylons as a mapped route. We'll fix that next. If you've built your extension properly, you should have a my_extension/plugins.py, to which you'll need to add the following to your plugin's class definition:

    class AmazingPlugin(plugins.SingletonPlugin, tk.DefaultDatasetForm):
        #or
        plugins.implements(plugins.IRoutes, inherit=True)
        def before_map(self, m):
            m.connect('amazing', #name of path route
                '/amazing', #url to map path to
                controller='ckanext.my_extension.controller:AmazingController', #controller
                action='amazing') #controller action (method)
            return m
    

    ..where ckanext.my_extension.controller is the include path to my_extension/controller.py, which we'll create next. It should consist of:

    import ckan.plugins as p
    from ckan.lib.base import BaseController
    
    class AmazingController(BaseController):
        def amazing(self):
            return p.toolkit.render('amazing.html')
    

    That's it. Now you've got a controller mapping a url to a nav item that you can call with h.build_nav_main(). Simple, right? ;) One last thing. You'll need to restart apache for it to take effect.

    Edit: there was a misspelling in the header.html part