使用 idatasetform 客製化資料說明欄位
- 客製化欄位需要透過 plugin 方式來完成,故底下說明將先新增一個 idatasetform plugin,並安裝於 ckan 中,後透過組態檔將此新模組開啟。
新增一個 plugin 模組
透過 ckan 虛擬機創建模組的模版,如下:
# 先進入虛擬機環境
. /usr/lib/ckan/default/bin/activate
# 移動到要放置模組的資料夾
cd /usr/lib/ckan/default/src/ckan/ckanext
# 創建一個模組
# ckanext-<模組名稱> : CKAN 模組名稱需要以 ckanext- 為開頭
# paster --plugin=ckan create -t ckanext ckanext-<模組名稱>
# 假設 plugin 名稱為 ExampleIDatasetForm
paster --plugin=ckan create -t ckanext ckanext-ExampleIDatasetForm
創建後會有許多的資訊需要輸入,如下:
# 一行描述此 plugin
Enter description (a one-line description of the extension, for example: "A simple blog extension for CKAN") ['']
# 此 plugin 開發者
Enter author (for example: "Guybrush Threepwood") ['']:
# 此開發者 e-mail
Enter author_email (for example: "[email protected]") ['']:
# plugin 關鍵字
Enter keywords (a space-separated list of keywords, for example: "CKAN blog") ['']:
# plugin 的 github 儲存庫資訊
Enter github_user_name (your GitHub user or organization name, for example: "guybrush" or "ckan") ['']:
創建完後,於此位置便有 plugin 相關安裝等預設內容:
/usr/lib/ckan/default/src/ckan/ckanext/ckanext-ExampleIDatasetForm/
- ckanext_iauthfunctions.egg_info : 自動產生的專案 metadata,一般而言不需要特別處理
- setup.py : 安裝 plugin 所需的 script
- ckanext/ExampleIDatasetForm/ : plugin 使用的所有 source code 放置的位置
建立新增欄位模組
- 於 CKAN 2.5.1 版本中,於 /usr/lib/ckan/default/src/ckan/ckanext/ 資料夾下,已有 idatasetform 範例模組,稱為「example_idatasetform」。
註解 |
---|
可以透過 http://URL/api/util/status 方式來查看 CKAN 版本 |
- 可以將此資料夾下的內容複製到新產生的 plugin 資料夾中
# 移動到 ckanext 資料夾下
cd /usr/lib/ckan/default/src/ckan/ckanext/
# 將 example_idatasetform 底下的 plugin.py 與資料夾 templates 整個複製到新建立模組資料夾中放置原始碼的資料夾中
cp -r ./example_idatasetform/plugin.py ./example_idatasetform/templates ./ckanext-ExampleIDatasetForm/ckanext/ExampleIDatasetForm/
修改模組
- 透過修改 plugin.py 的 schemas 便可以新增額外的欄位,可以複寫下列五項函式來達成:
函式 | 說明 |
---|---|
create_package_schema() | Return the schema for validating new dataset dicts. |
update_package_schema() | Return the schema for validating updated dataset dicts. |
show_package_schema() | Return a schema to validate datasets before they’re shown to the user. |
is_fallback() | Return True if this plugin is the fallback plugin. |
package_types() | Return an iterable of package types that this plugin handles. |
- 創建 plugin.py 類別
創建一個名為 ExampleIDatasetFormPlugins 的類別於 plugin.py 中,此類別實作 IDatasetform 介面並繼承 SingletonPlugin 與 DefaultDatasetForm。
# encoding: utf-8
import ckan.plugins as p
import ckan.plugins.toolkit as tk
class ExampleIDatasetFormPlugin(p.SingletonPlugin, tk.DefaultDatasetForm):
p.implements(p.IDatasetForm)
- 創建 CKAN 資料表綱目
def create_package_schema(self):
schema = super(ExampleIDatasetFormPlugin, self).create_package_schema()
schema = self._modify_package_schema(schema)
# add custom field
schema.update({
'custom_text': [tk.get_validator('ignore_missing'),tk.get_converter('convert_to_extras')]
})
return schema
- 更新 CKAN 資料表綱目
def update_package_schema(self):
schema = super(ExampleIDatasetFormPlugin, self).update_package_schema()
schema = self._modify_package_schema(schema)
# add custom field
schema.update({
'custom_text': [tk.get_validator('ignore_missing'),tk.get_converter('convert_to_extras')]
})
return schema
- 修改呈現資料表綱目
def show_package_schema(self):
schema = super(ExampleIDatasetFormPlugin, self).show_package_schema()
# Don't show vocab tags mixed in with normal 'free' tags
# (e.g. on dataset pages, or on the search page)
schema['tags']['__extras'].append(tk.get_converter('free_tags_only'))
# Add our custom_text field to the dataset schema.
# add custom field
schema.update({
'custom_text': [tk.get_converter('convert_from_extras'),
tk.get_validator('ignore_missing')]
})
schema['resources'].update({
'custom_resource_text' : [ tk.get_validator('ignore_missing') ]
})
return schema
- 資料集型態
def is_fallback(self):
# Return True to register this plugin as the default handler for
# package types not handled by any other IDatasetForm plugin.
return True
def package_types(self):
# This plugin doesn't handle any special package types, it just
# registers itself as the default (above).
return []
- 更新 templates
class ExampleIDatasetFormPlugin(plugins.SingletonPlugin, tk.DefaultDatasetForm):
'''An example IDatasetForm CKAN plugin.
Uses a tag vocabulary to add a custom metadata field to datasets.
'''
# add custom fields
plugins.implements(plugins.IConfigurer, inherit=False)
plugins.implements(plugins.IDatasetForm, inherit=False)
plugins.implements(plugins.ITemplateHelpers, inherit=False)
- 更新組態
def update_config(self, config):
# Add this plugin's templates dir to CKAN's extra_template_paths, so
# that CKAN will use this plugin's custom templates.
tk.add_template_directory(config, 'templates')
建立一個 package_metadata_fields.html
- 於 package/snippets/package_metadata_fields.html 加入底下內容
vim /usr/lib/ckan/default/src/ckan/ckanext/ckanext-ExampleIDatasetForm/ckanext/ExampleIDatasetForm/templates/package/snippets/package_metadata_fields.html
{% ckan_extends %}
{# You could remove 'free extras' from the package form like this, but we keep them for this example's tests.
{% block custom_fields %}
{% endblock %}
#}
{% block package_metadata_fields %}
<div class="control-group">
<label class="control-label" for="field-country_code">{{ _("Country Code") }}</label>
<div class="controls">
<select id="field-country_code" name="country_code" data-module="autocomplete">
{% for country_code in h.country_codes() %}
<option value="{{ country_code }}" {% if country_code in data.get('country_code', []) %}selected="selected"{% endif %}>{{ country_code }}</option>
{% endfor %}
</select>
</div>
</div>
{{ super() }}
{% endblock %}
- 修改 package_basic_fields.html
vim /usr/lib/ckan/default/src/ckan/ckanext/ckanext-ExampleIDatasetForm/ckanext/ExampleIDatasetForm/templates/package/snippets/package_basic_fields.html
{% ckan_extends %}
{% block package_basic_fields_custom %}
{{ form.input('custom_text', label=_('Custom Text'), id='field-custom_text', placeholder=_('custom text'), value=data.custom_text, error=errors.custom_text, classes=['control-medium']) }}
{% endblock %}
- 修改 additional_info.html
vim /usr/lib/ckan/default/src/ckan/ckanext/ckanext-ExampleIDatasetForm/ckanext/ExampleIDatasetForm/templates/package/snippets/package_basic_fields.html
此 html 中所列的 "Custom Text" 為顯示在畫面上的內容,若此內容無對應其他語言,則會以此 html 內容為主,如 "Test Info" 無對應中文,則中文畫面亦會顯示 "Test Info"。
{% ckan_extends %}
{% block extras %}
{% if pkg_dict.custom_text %}
<tr>
<th scope="row" class="dataset-label">{{ _("Custom Text") }}</th>
<td class="dataset-details">{{ pkg_dict.custom_text }}</td>
</tr>
{% endif %}
{% endblock %}
將此 plugin 加入 setup.py
- 準備 setup.py 檔案
vim /usr/lib/ckan/default/src/ckan/ckanext/ckanext-ExampleIDatasetForm/setup.py
# 「ExampleIDatasetForm=ckanext...」中 ExampleIDatasetForm 為之後加入 CKAN 使用的 plugin 名稱
# 「plugin:ExampleIDatasetFormPlugin」中 ExampleIDatasetFormPlugin 為 plugin 的類別名稱
entry_points='''
[ckan.plugins]
ExampleIDatasetForm=ckanext.ExampleIDatasetForm.plugin:ExampleIDatasetFormPlugin
[babel.extractors]
ckan = ckan.lib.extract:extract_ckan
''',
- 安裝此 plugin
# 先進入虛擬機
. /usr/lib/ckan/default/bin/activate
# 進入該 plugin 所在路徑
cd /usr/lib/ckan/default/src/ckan/ckanext/ckanext-ExampleIDatasetForm
# 開始安裝於測試階段,此時先安裝為 develop
python setup.py develop
- 使用此 plugin : 以開發環境為優先
vim /etc/ckan/default/development.ini
並於 ckan.plugins 後加入 ExampleIDatasetForm,如下
ckan.plugins = stats text_view image_view recline_view ExampleIDatasetForm
開始測試
因選擇 development 進行使用此 plugin,故執行 develop 環境來進行測試
# 先進入虛擬機環境
. /usr/lib/ckan/default/bin/activate
# 以測試組態檔來開啟新的 server 進行測試
$ paster serve /etc/ckan/default/development.ini
Starting server in PID 13961.
serving on 0.0.0.0:5000 view at http://127.0.0.1:5000