[ckan-dev] Repeatable metadata elements
Khalegh Mamakani
khalegh at highwaythreesolutions.com
Wed Apr 2 18:38:24 UTC 2014
Hello Pabitra,
I asked the same question a while ago but I didn’t get any answers. I had to add multiple values for a group of fields like contact name, contact email, etc. I checked ckan src for schema definition and came up with the following solution which I am not sure if it is the best way of doing it.
In my dataset form class I am overriding create_package_schema, update_package_schema, show_package_schema. Both create_package_schema and update_package_schema use the same schema definition. Here is part of the schema containing the multi value fields :
schema.update({
... ,
'contacts' : contacts_db_schema(),
'dates' : dates_to_db_schema(),
... ,
})
def contacts_db_schema():
schema = {
'name' : [check_empty, convert_to_extras],
'organization' : [check_empty, convert_to_extras],
'email' : [check_empty, valid_email, convert_to_extras],
'role' : [check_empty, convert_to_extras],
'private' : [ignore_missing, convert_to_extras],
'delete' :[ignore_missing, convert_to_extras]
}
return schema
Ckan uses this schema when creating or updating a dataset. It generates keys like (contacts, 0, name) or (contacts, 0, email) which are used by convert_to_extras convertor function.
I tried to do the same for show_package_schema, but ckan doesn’t give me the same key for fields so that I can use them to get the corresponding values from extras. The other problem is that ckan’s default convert_to_extras function takes the last part of the key when storing the data in extras which obviously doesn’t work when having multiple values.
For show_package_schema I am simply updating the schema as follow :
def show_package_schema(self):
schema = super(DatasetFormClass, self).show_package_schema()
schema['tags']['__extras'].append(toolkit.get_converter('free_tags_only'))
schema.update({
'contacts' : [convert_from_extras, ignore_missing],
'dates' : [convert_from_extras, ignore_missing],
})
Then I had to override both convert_to_extras and convert_from_extras. Be careful you cannot use the same converters for resources, you need to use ckan’s default if you have extra fields for resources.
def convert_to_extras(key, data, errors, context):
# print "key :====> ", key, "data : ====>", data[key]
extras = data.get(('extras',), [])
if not extras:
data[('extras',)] = extras
keyStr = ':'.join([str(x) for x in key])
extras.append({'key': keyStr, 'value': data[key]})
def convert_from_extras(key, data, errors, context):
print "key : <====", key, "\n"
def remove_from_extras(data, keyList):
to_remove = []
for data_key, data_value in data.iteritems():
if (data_key[0] == 'extras' and data_key[1] in keyList) :
to_remove.append(data_key)
for item in to_remove:
del data[item]
indexList = [] # A list containing the index of items in extras to be removed.
new_data = {} #A new dictionary for data stored in extras with the given key
for data_key, data_value in data.iteritems():
if (data_key[0] == 'extras'
and data_key[-1] == 'key'):
#Extract the key components eparated by ':'
keyList = data_value.split(':')
#Check for multiple value inputs and convert the list item index to integer
if (len(keyList) > 1):
keyList[1] = int(keyList[1])
#Construct the key for the stored value(s)
newKey = tuple(keyList)
if (key[-1] == newKey[0]):
#Retrieve data from extras and add it to new_data so it can be added to the data dictionary.
new_data[newKey] = data[('extras', data_key[1], 'value')]
#Add the data index in extras to the list of items to be removed.
indexList.append(data_key[1])
#print new_data
#Remove all data from extras with the given index
remove_from_extras(data, indexList)
#Remove previous data stored under the given key
del data[key]
deleteIndex = []
for data_key, data_value in new_data.iteritems():
#If this is a deleted record then add it to the deleted list to be removed from data later.
if ('delete' in data_key
and data_value == '1'):
deleteIndex.append(data_key[1])
deleted = []
for data_key, data_value in new_data.iteritems():
if (len(data_key) > 1
and data_key[1] in deleteIndex):
deleted.append(data_key)
for item in deleted :
del new_data[item]
#Add data extracted from extras to the data dictionary
for data_key, data_value in new_data.iteritems():
data[data_key] = data_value
I am attaching my template and javascript for contacts here as well. I hope this helps. Please let me know if you have any problem with the code.
Best,
Khalegh
On Apr 2, 2014, at 10:47 AM, Pabitra Dash <pkdash_reena at hotmail.com> wrote:
> Hi All,
>
> I have implemented a custom metadata schema for dataset. We have another requirement to make some of the metadata elements repeatable. For example, I have creator element and creator_email element which I want to make repeatable. So in the UI when the user selects add a creator, I should be able to store name and email for another creator. Not sure how I define a schema for these kind of repeatable elements.
>
> Would appreciate any help on this.
>
> Pabitra
>
>
>
> _______________________________________________
> ckan-dev mailing list
> ckan-dev at lists.okfn.org
> https://lists.okfn.org/mailman/listinfo/ckan-dev
> Unsubscribe: https://lists.okfn.org/mailman/options/ckan-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.okfn.org/pipermail/ckan-dev/attachments/20140402/588a6212/attachment-0012.html>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.okfn.org/pipermail/ckan-dev/attachments/20140402/588a6212/attachment-0013.html>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.okfn.org/pipermail/ckan-dev/attachments/20140402/588a6212/attachment-0014.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: contacts.js
Type: text/javascript
Size: 3369 bytes
Desc: not available
URL: <http://lists.okfn.org/pipermail/ckan-dev/attachments/20140402/588a6212/attachment-0003.bin>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.okfn.org/pipermail/ckan-dev/attachments/20140402/588a6212/attachment-0015.html>
More information about the ckan-dev
mailing list