GitHub PullRequestReviewCommentEvent at 2014-01-30 15:10:43
Repository: ckan
Actor: seanh
Payload: {"comment":{"url":"https://api.github.com/repos/ckan/ckan/pulls/comments/9308000","id":9308000,"diff_hunk":"@@ -0,0 +1,282 @@\n+============================\n+Adding custom fields to CKAN\n+============================\n+\n+Storing additional metadata for a dataset beyond the default metadata in CKAN\n+is a common scenario. CKAN provides a simple way to do this by allowing you to\n+abitrary key/value pairs against a dataset when creating or updating the\n+dataset, these appear under the \"Additional Information\" section on the web\n+interface and in 'extras' field of the JSON when accessed via in the API.\n+\n+These default extras can only take strings for their keys and values, no\n+validation is applied to the inputs and you cannot make them mandatory or\n+restrict the possible values you can take. By using CKAN's IDatasetForm plugin\n+interface, a CKAN plugin can add custom, first-class metadata fields to CKAN\n+datasets, and can do custom validation of these fields.  In this tutorial we\n+are assuming that you have read the :doc:`/extensions/tutorial`\n+\n+CKAN schemas and validation\n+---------------------------\n+When calls are made to the action functions, either via the web interface or\n+the CKAN API, the parameters passed to the action function usually have an\n+associated schema. For each parameter provided, the schema will contain a list\n+of functions that will take the value of the parameter and run it against each\n+function. These functions can provide validation, that can raise an error if\n+the value fails validation or it may be a converter that provides a lookup\n+for the action function to use.\n+\n+For example, the schemas can allow optional values by using the\n+:func:`~ckan.lib.navl.validators.ignore_missing` validator or check that a\n+dataset exists using :func:`~ckan.logic.validators.package_id_exists`. A list\n+of available validators and converters can be found at the :doc:`validators` \n+and :doc:`converters`.\n+\n+We will customizing these schemas to add our additional fields. The \n+:py:class:`~ckan.plugins.interfaces.IDatasetForm` interface allows us to \n+override the schemas for creation, updating and displaying of datasets.\n+\n+.. autosummary::\n+\n+   ~ckan.plugins.interfaces.IDatasetForm.create_package_schema\n+   ~ckan.plugins.interfaces.IDatasetForm.update_package_schema\n+   ~ckan.plugins.interfaces.IDatasetForm.show_package_schema\n+   ~ckan.plugins.interfaces.IDatasetForm.is_fallback\n+   ~ckan.plugins.interfaces.IDatasetForm.package_types\n+\n+The IDatasetForm also has other additional functions that allow you to\n+provide a custom template to be rendered for the CKAN frontend, but we will\n+not be using them for this tutorial.\n+\n+Adding custom fields to datasets\n+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n+\n+Create a new plugin named ``ckanext-extrafields`` and create a class named\n+``ExampleIDatasetFormPlugins`` inside \n+``ckanext-extrafields/ckanext/extrafields/plugins.py`` that implements the \n+``IDatasetForm`` interface and inherits from ``SingletonPlugin`` and \n+``DefaultDatasetForm``.\n+\n+.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py\n+    :end-before: def create_package_schema(self):\n+\n+Updating the CKAN schema\n+^^^^^^^^^^^^^^^^^^^^^^^^\n+\n+The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.create_package_schema`\n+function is used whenever a new dataset is created, we'll want update the \n+default schema and insert our custom field here.  We will fetch the default\n+schema defined in \n+:py:func:`~ckan.logic.schema.default_create_package_schema` by running \n+:py:meth:`~ckan.plugins.interfaces.IDatasetForm.create_package_schema`'s\n+super function and update it.\n+\n+.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py\n+    :pyobject: ExampleIDatasetFormPlugin.create_package_schema\n+\n+The CKAN schema is a dictionary where the key is the name of the field and the\n+value is a list of validators and converters. Here we have a validator to tell\n+CKAN to not raise a validation error if the value is missing and a converter to\n+convert the value to and save as an extra. We will want to change the\n+:py:meth:`~ckan.plugins.interfaces.IDatasetForm.update_package_schema` function\n+with the same update code.\n+\n+.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py\n+    :pyobject: ExampleIDatasetFormPlugin.update_package_schema\n+\n+The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.show_package_schema` is used\n+when the :py:func:`~ckan.logic.action.get.package_show` action is called, we\n+want the default_show_package_schema to be updated to include our custom field.\n+This time, instead of converting to an an extras field. We want our field to be\n+converted *from* an extras field. So we want to use the\n+:py:meth:`~ckan.logic.converters.convert_from_extras` converter.\n+\n+.. literalinclude:: ../../ckanext/example_idatasetform/plugin_v1.py\n+    :emphasize-lines: 4\n+    :pyobject: ExampleIDatasetFormPlugin.show_package_schema\n+\n+\n+Package types\n+^^^^^^^^^^^^^\n+\n+The :py:meth:`~ckan.plugins.interfaces.IDatasetForm.package_types` function \n+defines a list of package types that this plugin handles. Each package has a \n+field containing it's type. Plugins can register to handle specific types of ","path":"doc/extensions/adding-custom-fields.rst","position":103,"original_position":103,"commit_id":"5c45078fad938cda4fb4926a738b1d0c5eea10ad","original_commit_id":"5c45078fad938cda4fb4926a738b1d0c5eea10ad","user":{"login":"seanh","id":22498,"avatar_url":"https://gravatar.com/avatar/a1ffa12aad35d18f4463e4d18f9c54d8?d=https%3A%2F%2Fidenticons.github.com%2Ff23bbde4a364522ebe72204971af9e4d.png&r=x","gravatar_id":"a1ffa12aad35d18f4463e4d18f9c54d8","url":"https://api.github.com/users/seanh","html_url":"https://github.com/seanh","followers_url":"https://api.github.com/users/seanh/followers","following_url":"https://api.github.com/users/seanh/following{/other_user}","gists_url":"https://api.github.com/users/seanh/gists{/gist_id}","starred_url":"https://api.github.com/users/seanh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/seanh/subscriptions","organizations_url":"https://api.github.com/users/seanh/orgs","repos_url":"https://api.github.com/users/seanh/repos","events_url":"https://api.github.com/users/seanh/events{/privacy}","received_events_url":"https://api.github.com/users/seanh/received_events","type":"User","site_admin":false},"body":"it's -> its","created_at":"2014-01-30T15:10:43Z","updated_at":"2014-01-30T15:10:43Z","html_url":"https://github.com/ckan/ckan/pull/790#discussion_r9308000","pull_request_url":"https://api.github.com/repos/ckan/ckan/pulls/790","_links":{"self":{"href":"https://api.github.com/repos/ckan/ckan/pulls/comments/9308000"},"html":{"href":"https://github.com/ckan/ckan/pull/790#discussion_r9308000"},"pull_request":{"href":"https://api.github.com/repos/ckan/ckan/pulls/790"}}}}