Skip to content

Aggregate data values

DataValue and DataValueSet — the typed wire shapes for DHIS2's aggregate-data path (/api/dataValueSets GET / POST and the per-value /api/dataValues endpoint). Pairs with Data values (streaming), which exposes the same shape via client.data_values.stream(...) for very large imports.

When to reach for it

  • Pushing a small or medium batch of aggregate values from a script (CSV-to-DHIS2 sync, ETL pipeline, integration test fixture).
  • Reading values back to verify a write landed or to drive an analytics-side check.
  • Building the typed payload the streaming accessor and the bulk-grouped helper both consume.

Worked example — typed write, then read-back

from dhis2w_client import DataValue, DataValueSet
from dhis2w_core.client_context import open_client
from dhis2w_core.profile import profile_from_env

async with open_client(profile_from_env()) as client:
    # Push two values. `import_grouped_by_dataset` is the cross-version
    # write path (required on v43 BUGS #35, accepted on v41 + v42). The
    # typed `DataValue`s are validated by pydantic before they hit the wire.
    values = [
        DataValue(
            dataElement="fbfJHSPpUQD",
            period="202604",
            orgUnit="ImspTQPwCqd",
            categoryOptionCombo="HllvX50cXC0",
            attributeOptionCombo="HllvX50cXC0",
            value="42",
        ),
        DataValue(
            dataElement="fbfJHSPpUQD",
            period="202605",
            orgUnit="ImspTQPwCqd",
            categoryOptionCombo="HllvX50cXC0",
            attributeOptionCombo="HllvX50cXC0",
            value="43",
        ),
    ]
    # `import_grouped_by_dataset` POSTs one envelope per DataSet group
    # (required on v43 BUGS #35). Returns a list — one WebMessageResponse
    # per POST. Aggregate the per-envelope counts to get a total.
    envelopes = await client.data_values.import_grouped_by_dataset(values)
    total_imported = sum((env.import_count().imported if env.import_count() else 0) for env in envelopes)
    print(f"posted {len(envelopes)} group(s)  total imported={total_imported}")
    for env in envelopes:
        print(f"  status={env.status}  message={env.message!r}")

    # Read back. `/api/dataValueSets` returns the typed DataValueSet shape;
    # validate the raw dict through the pydantic model.
    raw = await client.get_raw(
        "/api/dataValueSets",
        params={"dataSet": "lyLU2wR22tC", "period": "202604", "orgUnit": "ImspTQPwCqd"},
    )
    dvs = DataValueSet.model_validate(raw)
    for v in dvs.dataValues or []:
        print(f"  DE={v.dataElement}  pe={v.period}  ou={v.orgUnit}  value={v.value}")

When to use which write path

import_grouped_by_dataset(values) is the safe cross-version default. It pre-fetches each DataElement's DataSet membership and POSTs one {"dataSet": …, "dataValues": [...]} envelope per group — required on DHIS2 v43 for any DE that belongs to multiple DataSets (BUGS #35: v43 rejects mixed batches with 409 E8002). v41 + v42 accept the same envelope shape, so the call is portable.

client.data_values.stream(values, ...) is the streaming alternative for very large imports — wraps the values as an async-byte stream so httpx doesn't have to materialise the full payload in memory.

aggregate

Typed models for DHIS2 aggregate data values (shim over generated/v42/oas).

Covers the /api/dataValueSets GET response (a DataValueSet envelope containing a list of DataValues). The corresponding POST/import path returns a WebMessageResponse (see dhis2w_client/envelopes.py).

Distinct from the generated DataElement / DataSet / CategoryOptionCombo metadata models (those come out of /api/schemas codegen) — these describe the runtime values captured against that metadata. OpenAPI ships both shapes under components/schemas/{DataValue,DataValueSet}.

Classes

DataValue

Bases: BaseModel

OpenAPI schema DataValue.

Source code in packages/dhis2w-client/src/dhis2w_client/generated/v42/oas/data_value.py
class DataValue(_BaseModel):
    """OpenAPI schema `DataValue`."""

    model_config = _ConfigDict(extra="allow", populate_by_name=True, defer_build=True)

    attributeOptionCombo: str | None = None
    categoryOptionCombo: str | None = None
    comment: str | None = None
    created: str | None = None
    dataElement: str | None = None
    deleted: bool | None = None
    followup: bool | None = None
    lastUpdated: str | None = None
    orgUnit: str | None = None
    period: str | None = None
    storedBy: str | None = None
    value: str | None = None

DataValueSet

Bases: BaseModel

OpenAPI schema DataValueSet.

Source code in packages/dhis2w-client/src/dhis2w_client/generated/v42/oas/data_value_set.py
class DataValueSet(_BaseModel):
    """OpenAPI schema `DataValueSet`."""

    model_config = _ConfigDict(extra="allow", populate_by_name=True, defer_build=True)

    attributeCategoryOptions: list[str] | None = None
    attributeOptionCombo: str | None = None
    categoryOptionComboIdScheme: str | None = None
    completeDate: str | None = None
    dataElementIdScheme: str | None = None
    dataSet: str | None = None
    dataSetIdScheme: str | None = None
    dataValues: list[DataValue] | None = None
    dryRun: bool | None = None
    idScheme: str | None = None
    orgUnit: str | None = None
    orgUnitIdScheme: str | None = None
    period: str | None = None
    strategy: str | None = None