How to use and reference forms and cases programatically
With the introduction of the new architecture for form and case data it is now necessary to use generic functions and accessors to access and operate on the models.
This document provides a basic guide for how to do that.
Models |
---|
CommCareCase |
CaseTransaction |
CaseAttachment |
CommCareCaseIndex |
XFormInstance |
XFormOperation |
Form Instance API
Property / method |
Description |
---|---|
form.form_id |
The instance ID of the form |
form.is_normal form.is_deleted form.is_archived form.is_error form.is_deprecated form.is_duplicate form.is_submission_error_log |
Replacement for checking the doc_type of a form |
form.attachments |
The form attachment objects |
form.get_attachment |
Get an attachment by name |
form.archive |
Archive a form |
form.unarchive |
Unarchive a form |
form.to_json |
Get the JSON representation of a form |
form.form_data |
Get the XML form data |
Case API
Property / method |
Description |
---|---|
case.case_id |
ID of the case |
case.is_deleted |
Replacement for doc_type check |
case.case_name |
Name of the case |
case.get_attachment |
Get attachment by name |
case.dynamic_case_properties |
Dictionary of dynamic case properties |
case.get_subcases |
Get subcase objects |
case.get_index_map |
Get dictionary of case indices |
Model acessors
To access models from the database there are classes that abstract the actual DB operations.
These classes are generally names <type>Accessors
and must be instantiated with a domain
name in order to know which DB needs to be queried.
Forms
XFormInstance.objects.get_form(form_id, domain)
XFormInstance.objects.get_forms(form_ids, domain)
XFormInstance.objects.iter_forms(form_ids, domain)
XFormInstance.objects.save_new_form(form)
only for new forms
XFormInstance.objects.get_with_attachments(form, domain)
Preload attachments to avoid having to the the DB again
Cases
CommCareCase.objects.get_case(case_id, domain)
CommCareCase.objects.get_cases(case_ids, domain)
CommCareCase.objects.iter_cases(case_ids, domain)
CommCareCase.objects.get_case_ids_in_domain(domain, type=’dog’)
Ledgers
LedgerAccessors(domain).get_ledger_values_for_case(case_id)
For more details see:
corehq.form_processor.interfaces.dbaccessors.LedgerAccessors
Unit Tests
To create a form in unit tests use the following pattern:
from corehq.form_processor.utils import get_simple_wrapped_form, TestFormMetadata
def test_my_form_function(self):
# This TestFormMetadata specifies properties about the form to be created
metadata = TestFormMetadata(
domain=self.user.domain,
user_id=self.user._id,
)
form = get_simple_wrapped_form(
form_id,
metadata=metadata
)
Creating cases can be done with the CaseFactory
:
from casexml.apps.case.mock import CaseFactory
def test_my_case_function(self):
factory = CaseFactory(domain='foo')
case = factory.create_case(
case_type='my_case_type',
owner_id='owner1',
case_name='bar',
update={'prop1': 'abc'}
)
Cleaning up
Cleaning up in tests can be done using the FormProcessorTestUtils1
class:
from corehq.form_processor.tests.utils import FormProcessorTestUtils
def tearDown(self):
FormProcessorTestUtils.delete_all_cases()
# OR
FormProcessorTestUtils.delete_all_cases(domain=domain)
FormProcessorTestUtils.delete_all_xforms()
# OR
FormProcessorTestUtils.delete_all_xforms(domain=domain)