Add a new tab, controller, page on CKAN

情境:
我們想要新增一些資料處理的功能
可能跟CKAN本來的Dataset沒有大太關係
所以我們需要新增一個tab,裡面放置我們自己的內容
原本的首頁
目標:新增一個Tab叫Data Cooking,並導到自己設定的頁面 helloChief.html
前置準備:
  • 安裝好 CKAN 2.7.2,可以參考官網教學或這一篇
  • 新增一個Plugin,完成到 這一步
    註: plugin 在官網有時也稱做 extension
我們plugin的名稱叫做 ytdataservice
ytdataservice plugin(圖左)與CKAN(圖右)的目錄結構如下:
 
ytdataservice plugin紅色標註的內容是與這次主題有關的檔案名稱
新增: header.html, helloChief.html, controllers.py
修改: plugin.html
首要目標,取代部分的Block
在CKAN的設計上,如果是想要取代掉原有檔案部分的block(區塊)
必須要與原本的CKAN目錄路徑一樣
在這,我們想在原本的 header_site_navigation_tabs 區塊新增一個tab
因此,我們就得在ytdataservice plugin所在目錄對應的位置新增 header.html
程式碼如下

templates/header.html

{% ckan_extends %}

{% block header_site_navigation_tabs %}
{{ h.build_nav_main(
  ('cookData', _('Data Cooking')),
  ('search', _('Datasets')),
  ('organizations_index', _('Organizations')),
  ('group_index', _('Groups')),
  ('about', _('About'))
) }}
{% endblock %}
因為我們並不是要完全取代,所以記得最上面一定要加上{% ckan_extends %}
接著就複製原有區塊的程式碼,加上我們自己的名稱
h.build_nav_main 是ckan提供建立menu item的方法
對應欄位的意義為 (Route名稱, _(前端顯示名稱))
既然有Route的名稱,我們就得新增這個Route對應到的Controller

plugin.py

import ckan.plugins as plugins
import ckan.plugins.toolkit as toolkit


class YtdataservicePlugin(plugins.SingletonPlugin):
    plugins.implements(plugins.IConfigurer)
    plugins.implements(plugins.IRoutes)

    # IConfigurer

    def update_config(self, config_):
        toolkit.add_template_directory(config_, 'templates')
        toolkit.add_public_directory(config_, 'public')
        toolkit.add_resource('fanstatic', 'ytdataservice')

    # IRoutes
    def before_map(self, map):
        map.connect('cookData','/cookingData/', controller='ckanext.ytdataservice.controllers:cookDataController', action='firstPage')
        return map

    def after_map(self, map):
        return map
透過 IConfigurer的interface,將我們plugin的檔案加到CKAN裡
若要實作客製化的Route
記得要新增 plugins.implements(plugins.IRoutes) 這行才能接著實作
map.connect(ROUTE名稱, URL_PATH, CONTROLLER, CONTROLLER的function)
從這我們可以發現,我們還需要一個class與對應的function來接這個request
所以接著下面的程式碼

controllers.py

import ckan.lib.base as base

class cookDataController(base.BaseController):
    def firstPage(self):
        return base.render('helloChief.html')
    pass
BaseController也是CKAN原有的,其他的controller要再研究
我們就render一個新頁面給它
這邊我們很簡單的寫個範例,不繼承原有的任何內容(原理同header.html)
只要檔名不要與原有或其他plugin一樣,就不會有取代的問題

/templates/helloChief.html

<h1> Hello Chief~ </h1>
最後重啟Server(Production)或在Console(Development)下以下指令:
paster serve /etc/ckan/default/development.ini
這樣子就可以在首頁點擊Cooking Data後,看到這個陽春的頁面啦~

留言