--- a/ckanext/example/controller_plugin.py +++ b/ckanext/example/controller_plugin.py @@ -1,24 +1,24 @@ -import logging -from ckan.lib.base import BaseController, render, c, model, abort, request -from ckan.lib.base import redirect, _, config, h +import os, logging +from ckan.authz import Authorizer import ckan.logic.action.create as create import ckan.logic.action.update as update import ckan.logic.action.get as get from ckan.logic.converters import date_to_db, date_to_form, convert_to_extras, convert_from_extras -from ckan.lib.navl.dictization_functions import DataError, flatten_dict, unflatten from ckan.logic import NotFound, NotAuthorized, ValidationError from ckan.logic import tuplize_dict, clean_dict, parse_params +import ckan.logic.schema as default_schema from ckan.logic.schema import package_form_schema -from ckan.plugins import IDatasetForm -from ckan.plugins import implements, SingletonPlugin +import ckan.logic.validators as val +from ckan.lib.base import BaseController, render, c, model, abort, request +from ckan.lib.base import redirect, _, config, h from ckan.lib.package_saver import PackageSaver from ckan.lib.field_types import DateType, DateConvertError -from ckan.authz import Authorizer from ckan.lib.navl.dictization_functions import Invalid -from ckanext.dgu.forms.package_gov_fields import GeoCoverageType from ckan.lib.navl.dictization_functions import validate, missing -import ckan.logic.validators as val -import ckan.logic.schema as default_schema +from ckan.lib.navl.dictization_functions import DataError, flatten_dict, unflatten +from ckan.plugins import IDatasetForm, IConfigurer +from ckan.plugins import implements, SingletonPlugin + from ckan.lib.navl.validators import (ignore_missing, not_empty, empty, @@ -28,38 +28,42 @@ log = logging.getLogger(__name__) -geographic_granularity = [('', ''), - ('national', 'national'), - ('regional', 'regional'), - ('local authority', 'local authority'), - ('ward', 'ward'), - ('point', 'point'), - ('other', 'other - please specify')] - -update_frequency = [('', ''), - ('never', 'never'), - ('discontinued', 'discontinued'), - ('annual', 'annual'), - ('quarterly', 'quarterly'), - ('monthly', 'monthly'), - ('other', 'other - please specify')] - -temporal_granularity = [("",""), - ("year","year"), - ("quarter","quarter"), - ("month","month"), - ("week","week"), - ("day","day"), - ("hour","hour"), - ("point","point"), - ("other","other - please specify")] -class ExamplePackageController(SingletonPlugin): +class ExampleDatasetForm(SingletonPlugin): + """This plugin demonstrates how a theme packaged as a CKAN + extension might extend CKAN behaviour. + In this case, we implement three extension interfaces: + + - ``IConfigurer`` allows us to override configuration normally + found in the ``ini``-file. Here we use it to specify where the + form templates can be found. + - ``IDatasetForm`` allows us to provide a custom form for a dataset + based on the type_name that may be set for a package. Where the + type_name matches one of the values in package_types then this + class will be used. + """ implements(IDatasetForm, inherit=True) + implements(IConfigurer, inherit=True) + + def update_config(self, config): + """ + This IConfigurer implementation causes CKAN to look in the + ```templates``` directory when looking for the package_form() + """ + here = os.path.dirname(__file__) + rootdir = os.path.dirname(os.path.dirname(here)) + template_dir = os.path.join(rootdir, 'ckanext', + 'example', 'theme', 'templates') + config['extra_template_paths'] = ','.join([template_dir, + config.get('extra_template_paths', '')]) def package_form(self): + """ + Returns a string representing the location of the template to be + rendered. e.g. "package/new_package_form.html". + """ return 'controller/package_plugin.html' def is_fallback(self): @@ -85,14 +89,13 @@ """ return ["example"] - def _setup_template_variables(self, context, data_dict=None): + def setup_template_variables(self, context, data_dict=None): + """ + Adds variables to c just prior to the template being rendered that can + then be used within the form + """ c.licences = [('', '')] + model.Package.get_license_options() - c.geographic_granularity = geographic_granularity - c.update_frequency = update_frequency - c.temporal_granularity = temporal_granularity - - c.publishers = self.get_publishers() - + c.publishers = [('Example publisher', 'Example publisher 2')] c.is_sysadmin = Authorizer().is_sysadmin(c.user) c.resource_columns = model.Resource.get_columns() @@ -102,8 +105,11 @@ c.auth_for_change_state = Authorizer().am_authorized( c, model.Action.CHANGE_STATE, pkg) - def _form_to_db_schema(self): - + def form_to_db_schema(self): + """ + Returns the schema for mapping package data from a form to a format + suitable for the database. + """ schema = { 'title': [not_empty, unicode], 'name': [not_empty, unicode, val.name_validator, val.package_name_validator], @@ -112,16 +118,6 @@ 'date_released': [date_to_db, convert_to_extras], 'date_updated': [date_to_db, convert_to_extras], 'date_update_future': [date_to_db, convert_to_extras], - 'update_frequency': [use_other, unicode, convert_to_extras], - 'update_frequency-other': [], - 'precision': [unicode, convert_to_extras], - 'geographic_granularity': [use_other, unicode, convert_to_extras], - 'geographic_granularity-other': [], - 'geographic_coverage': [ignore_missing, convert_geographic_to_db, convert_to_extras], - 'temporal_granularity': [use_other, unicode, convert_to_extras], - 'temporal_granularity-other': [], - 'temporal_coverage-from': [date_to_db, convert_to_extras], - 'temporal_coverage-to': [date_to_db, convert_to_extras], 'url': [unicode], 'taxonomy_url': [unicode, convert_to_extras], @@ -144,18 +140,16 @@ } return schema - def _db_to_form_schema(data): + def db_to_form_schema(data): + """ + Returns the schema for mapping package data from the database into a + format suitable for the form (optional) + """ schema = { 'date_released': [convert_from_extras, ignore_missing, date_to_form], 'date_updated': [convert_from_extras, ignore_missing, date_to_form], 'date_update_future': [convert_from_extras, ignore_missing, date_to_form], - 'update_frequency': [convert_from_extras, ignore_missing, extract_other(update_frequency)], 'precision': [convert_from_extras, ignore_missing], - 'geographic_granularity': [convert_from_extras, ignore_missing, extract_other(geographic_granularity)], - 'geographic_coverage': [convert_from_extras, ignore_missing, convert_geographic_to_form], - 'temporal_granularity': [convert_from_extras, ignore_missing, extract_other(temporal_granularity)], - 'temporal_coverage-from': [convert_from_extras, ignore_missing, date_to_form], - 'temporal_coverage-to': [convert_from_extras, ignore_missing, date_to_form], 'taxonomy_url': [convert_from_extras, ignore_missing], 'resources': default_schema.default_resource_schema(), @@ -177,47 +171,10 @@ } return schema - def _check_data_dict(self, data_dict): + def check_data_dict(self, data_dict): + """ + Check if the return data is correct and raises a DataError if not. + """ return - def get_publishers(self): - return [('pub1', 'pub2')] - -def use_other(key, data, errors, context): - - other_key = key[-1] + '-other' - other_value = data.get((other_key,), '').strip() - if other_value: - data[key] = other_value - -def extract_other(option_list): - - def other(key, data, errors, context): - value = data[key] - if value in dict(option_list).keys(): - return - elif value is missing: - data[key] = '' - return - else: - data[key] = 'other' - other_key = key[-1] + '-other' - data[(other_key,)] = value - return other - -def convert_geographic_to_db(value, context): - - if isinstance(value, list): - regions = value - elif value: - regions = [value] - else: - regions = [] - - return GeoCoverageType.get_instance().form_to_db(regions) - -def convert_geographic_to_form(value, context): - - return GeoCoverageType.get_instance().db_to_form(value) -