Python module for accessing ODK Aggregate

Good day here,
I'm new to all this ODK data collection and aggregation story, so please bear with me.
I am organizing data collection inside of a botanical garden, people would walk through the garden with their Android pocket computer, running ODK Collect and ZXing, they would scan plant labels, add information about the plant, get back to office, upload their forms to a ODK aggregate server, and here comes the complication.
I need the collected information to reach our database, the interaction I envision is from the desktop software we use (GPL, and I am the maintainer), a simple menu item initiating data download from the ODK Aggregate server to our database.
I know one way how to do this, but it's so clumsy that I can't believe there isn't an easier solution.

What I would do is invoke ODK-Briefcase, download everything from the ODK Aggregate server to the localhost, then parse the downloaded information into our desktop program.

what I would like is to avoid ODK-Briefcase and use a native Python library, letting me get the data straight into the desktop software we use.

well, in the meanwhile I've written this:

from requests.auth import HTTPDigestAuth
import requests
import xml.etree.ElementTree as ET

def get_submissions(host, form_id, user, pw):
    base_format = 'https://%(host)s/view/%(api)s?formId=%(form_id)s'
    submission_format = '[@version=null and @uiVersion=null]/%(group_name)s[@key=%(uuid)s]'
    auth = HTTPDigestAuth(user, pw)
    result = requests.get(base_format % {'form_id': form_id,
                                         'api': 'submissionList',
                                         'host': host},
    root = ET.fromstring(result.text)
    idlist, cursor = [child for child in root]
    result = []
    for uuid in [i.text for i in idlist]:
        url = (base_format % {'form_id': form_id,
                              'api': 'downloadSubmission',
                              'host': host} +
               submission_format % {'group_name': 'plant_form',
                                    'uuid': uuid})
        reply = requests.get(url, auth=auth)
        root = ET.fromstring(reply.text)
        [data for data in root]
        [form for form in data]
        result.append(dict([(i.tag.replace('{}', ''), i.text) 
                            for i in form]))
    return result

and it is going to be part of ghini, which means GPL2+.

1 Like

Nice! That seems like a very good approach.

I was just looking at ghini a bit and it's a very cool project. If you want to spread the word that it has ODK integration, consider sharing in the Showcase!