Data sets¶
Two accessors on Dhis2Client cover the aggregate-capture parent and its optional section tree:
| Accessor | API path | Purpose |
|---|---|---|
client.data_sets |
/api/dataSets |
Aggregate-capture parent: period type + ordered DataSetElements + optional sections + per-OU assignment. |
client.sections |
/api/sections |
Ordered grouping of DEs inside one DataSet for the data-entry app. |
A DataSet is a collection of DataElements captured together for one period (monthly immunisation tally, weekly commodity stock, etc.). Sections optionally group + order the DEs inside the DataSet for rendering.
DataSetElements are a join table¶
Wiring a DataElement into a DataSet isn't a simple ref list — the join is a DataSetElement that carries an optional per-set CategoryCombo override (the common pattern where one DE is captured under different disaggregations per set). The accessor's add_element / remove_element helpers round-trip the full DataSet, mutate dataSetElements, and PUT it back so the override travels without a dedicated endpoint:
async with Dhis2Client(...) as client:
ds = await client.data_sets.create(
name="ANC Monthly",
short_name="ANCm",
period_type="Monthly",
open_future_periods=2,
expiry_days=10,
)
await client.data_sets.add_element(ds.id, "deFirstVisit")
await client.data_sets.add_element(ds.id, "deSecondVisit", category_combo_uid="ccAgeGroup")
Sections carry an ordered DE list¶
A DataSet can be sectionless (flat list) or ship multiple sections. The Data Entry app renders sections in sortOrder ascending; inside each section, DEs render in the order they appear in Section.dataElements[].
add_element appends by default, position=0 inserts at the front, reorder replaces the whole list in one PUT:
section = await client.sections.create(
name="Vaccination",
data_set_uid=ds.id,
sort_order=1,
data_element_uids=["deFirstVisit", "deSecondVisit"],
)
section = await client.sections.reorder(section.id, ["deSecondVisit", "deFirstVisit"])
No *Spec builder¶
Same call as the authoring triples — keyword args on the accessor.
Per-OU assignment¶
DataSet.organisationUnits[] is not yet exposed through a dedicated helper. The add-to-ou / remove-from-ou surface is on the roadmap as the natural next DataSet PR. For now, attach OUs via client.data_sets.update(ds) after mutating the model, or via metadata import.
Default CategoryCombo¶
DHIS2 rejects DataSets without a categoryCombo. Omit category_combo_uid on create to fall back to the instance's default combo (client.system.default_category_combo_uid()) — the common case.
CLI¶
dhis2 metadata data-sets list --period-type Monthly
dhis2 metadata data-sets create \
--name "ANC Monthly" --short-name "ANCm" --period-type Monthly \
--open-future-periods 2 --expiry-days 10
dhis2 metadata data-sets add-element <DS_UID> <DE_UID>
dhis2 metadata data-sets add-element <DS_UID> <DE_UID> --category-combo <CC_UID>
dhis2 metadata sections create \
--name "Vaccination" --data-set <DS_UID> --sort-order 1 \
--data-element <DE_A> --data-element <DE_B>
dhis2 metadata sections reorder <SECTION_UID> <DE_B> <DE_A>
Every list has an ls alias; every destructive verb accepts --yes / -y.
MCP¶
15 tools (metadata_data_set_* + metadata_section_*) mirror the CLI surface.
data_sets
¶
DataSet authoring — Dhis2Client.data_sets.
A DHIS2 DataSet is the collection of DataElements captured together
for one period (monthly immunisation tally, weekly commodity stock,
etc.). Generic CRUD lives on the generated accessor
(client.resources.data_sets); this module adds the authoring
primitives integration + admin flows need:
create(...)— named kwargs covering the minimal required subset (name,short_name,period_type) plus the optional references (category_combo,code,description) and the knobs most real DataSets carry (open_future_periods,expiry_days,timely_days).add_element(ds_uid, de_uid, *, category_combo_uid=None)— append a DataElement to the DataSet, with optional per-set CategoryCombo override. DataSetElements are the join table, not a simple ref list; the accessor round-trips the full DataSet, mutatesdataSetElements, and PUTs it back so thecategoryCombooverride can be carried without a dedicated endpoint.remove_element(ds_uid, de_uid)— same round-trip, filtered.rename(uid, ...)— partial-update shortcut for label fields.delete(uid)— DHIS2 rejects deletes on DataSets with saved values or a section tree.
No *Spec builder — continues the spec-audit data point from the
organisation-unit accessors.
Classes¶
DataSet
¶
Bases: BaseModel
Generated model for DHIS2 DataSet.
DHIS2 Data Set - persisted metadata (generated from /api/schemas at DHIS2 v42).
API endpoint: /api/dataSets.
Field Field(description=...) entries flag DHIS2 semantics the bare
type can't capture: which side of a relationship owns the link
(writable) vs the inverse side (ignored by the API), uniqueness
constraints, and length bounds.
Source code in packages/dhis2w-client/src/dhis2w_client/generated/v42/schemas/data_set.py
DataSetsAccessor
¶
Dhis2Client.data_sets — CRUD + membership helpers over /api/dataSets.
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | |
Functions¶
__init__(client)
¶
list_all(*, period_type=None, page=1, page_size=50)
async
¶
Page through DataSets, optionally filtered by periodType.
period_type=PeriodType.MONTHLY narrows to monthly DataSets.
Server-side paged — loop page until the returned list is
shorter than page_size for the full catalog.
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
get(uid)
async
¶
Fetch one DataSet by UID with its DSEs + sections + OUs resolved inline.
create(*, name, short_name, period_type, category_combo_uid=None, code=None, form_name=None, description=None, open_future_periods=None, expiry_days=None, timely_days=None, uid=None)
async
¶
Create a DataSet.
DHIS2 rejects DataSets without a categoryCombo — omit
category_combo_uid to fall back to the default combo
(client.system.default_category_combo_uid()). period_type is
required (Monthly, Weekly, Daily, Yearly, …). Use the
PeriodType StrEnum for typed access; a plain string is
accepted for the rare frequency not yet in the enum.
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
update(data_set)
async
¶
PUT an edited DataSet back. data_set.id must be set.
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
rename(uid, *, name=None, short_name=None, form_name=None, description=None)
async
¶
Partial-update shortcut — read, mutate label fields, PUT.
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
add_element(data_set_uid, data_element_uid, *, category_combo_uid=None)
async
¶
Append a DataElement to the DataSet.
Pass category_combo_uid to override the DE's own CategoryCombo
for this DataSet only (a common pattern when one DE is captured
under different disaggregations per set).
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
remove_element(data_set_uid, data_element_uid)
async
¶
Remove a DataElement from the DataSet.
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
delete(uid)
async
¶
Delete a DataSet — DHIS2 rejects deletes on DataSets with saved values.
Source code in packages/dhis2w-client/src/dhis2w_client/data_sets.py
sections
¶
Section authoring — Dhis2Client.sections.
A DHIS2 Section groups DataElements inside a DataSet for display in
the Data Entry app. A DataSet can be sectionless (flat list) or ship
multiple sections (monthly supply vs stock-out, ANC vs delivery, …).
Each Section carries an ordered dataElements[] reference list plus
optional indicators[] for the side pane.
Generic CRUD lives on the generated accessor (client.resources.sections);
this module adds the authoring primitives that matter for operators:
create(...)— named kwargs overname+ parentdata_set_uid+ optionalsort_order/description/ common toggles.list_for(data_set_uid)— narrow to one DataSet's sections in sort order.add_element/remove_element/reorder— the DE-ordering primitives a section-aware authoring flow needs.reordertakes a full list of DE UIDs and setsdataElementsto that ordering in one PUT.rename(uid, ...)— partial-update shortcut for label fields.delete(uid)— removes the section shell; DEs stay on the DataSet.
Classes¶
Section
¶
Bases: BaseModel
Generated model for DHIS2 Section.
DHIS2 Section - persisted metadata (generated from /api/schemas at DHIS2 v42).
API endpoint: /api/sections.
Field Field(description=...) entries flag DHIS2 semantics the bare
type can't capture: which side of a relationship owns the link
(writable) vs the inverse side (ignored by the API), uniqueness
constraints, and length bounds.
Source code in packages/dhis2w-client/src/dhis2w_client/generated/v42/schemas/section.py
SectionsAccessor
¶
Dhis2Client.sections — CRUD + ordering helpers over /api/sections.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | |
Functions¶
__init__(client)
¶
list_all(*, page=1, page_size=50)
async
¶
Page through Sections across every DataSet.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
list_for(data_set_uid)
async
¶
Return the Sections belonging to one DataSet, in sort order.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
get(uid)
async
¶
Fetch one Section by UID with its DE refs resolved inline.
create(*, name, data_set_uid, sort_order=None, description=None, code=None, data_element_uids=None, indicator_uids=None, show_column_totals=None, show_row_totals=None, uid=None)
async
¶
Create a Section attached to data_set_uid.
data_element_uids seeds the ordered DE list. If omitted, the
section starts empty and DEs can be added with add_element or
reorder afterward. sort_order controls where the section
renders in the DataSet; sections are ordered ascending.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
update(section)
async
¶
PUT an edited Section back. section.id must be set.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
rename(uid, *, name=None, description=None, sort_order=None)
async
¶
Partial-update shortcut — read, mutate label / order, PUT.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
add_element(section_uid, data_element_uid, *, position=None)
async
¶
Append (or insert at position) a DataElement to the Section.
DHIS2 preserves the order of dataElements[] for data-entry
rendering. position is 0-indexed; omit to append.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
remove_element(section_uid, data_element_uid)
async
¶
Remove a DataElement from the Section without touching the DataSet.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
reorder(section_uid, data_element_uids)
async
¶
Replace the Section's dataElements with exactly data_element_uids, in order.
Any DE UID not in the list is dropped from the Section. Missing UIDs aren't checked against the parent DataSet here — a subsequent render or validation run catches the inconsistency.
Source code in packages/dhis2w-client/src/dhis2w_client/sections.py
delete(uid)
async
¶
Delete a Section — DEs stay on the parent DataSet.