References/Observation
More languages
More actions
An Observation is one named, coded data point about a subject — almost always a patient: a blood pressure reading, a temperature, a coded answer captured through a questionnaire. main_code records what was observed (usually bound to LOINC) and value holds the result. You rarely create one by hand; most observations are materialized when a questionnaire is submitted.
The model is just storage; several fields are opaque JSONFields. Their real structure lives in the Pydantic resource specs under care/emr/resources/observation/, which own the enums, nested JSON shapes, validation, and the read/write schema split. Each field row below gives the storage column first, then the shape the spec enforces on top of it.
Models
| Model | Purpose |
|---|---|
Observation
|
A single coded measurement or finding about a patient, captured within an encounter |
Observation extends EMRBaseModel, the shared Care EMR base that supplies external_id, created_date/modified_date, soft-delete via deleted, created_by/updated_by, and history/meta JSON.
Observation fields
Classification & coding
| Field | Storage type | Spec shape / notes |
|---|---|---|
status
|
CharField(255)
|
Enum ObservationStatus — final, amended, entered_in_error. Required in specs. Questionnaire-sourced observations land as final
|
is_group
|
BooleanField
|
Default False. True marks a grouping/panel observation that holds component/child observations instead of a single value. Not exposed in the resource specs
|
category
|
JSONField (default {})
|
Spec: optional Coding { system?, version?, code, display? }. FHIR observation category, derived from the questionnaire
|
main_code
|
JSONField (default {})
|
Spec: optional Coding. What is being observed, typically LOINC (CARE_OBSERVATION_VALUSET, system http://loinc.org)
|
alternate_coding
|
JSONField (default [])
|
Spec: optional CodeableConcept { id?, coding?: Coding[], text }. Same concept expressed in other code systems
|
Subject & context
| Field | Storage type | Spec shape / notes |
|---|---|---|
subject_type
|
CharField(255)
|
Enum SubjectType — patient, encounter. Spec defaults to encounter
|
subject_id
|
UUIDField
|
The subject entity's id. Set server-side; not in the spec body |
patient
|
FK → Patient
|
CASCADE. Set server-side, not in the spec body
|
encounter
|
FK → Encounter
|
None. Where the observation was recorded |
effective_datetime
|
DateTimeField
|
When the observation was effective. Nullable in storage, but the spec requires a tz-aware datetime on create; optional on update
|
Author & performer
| Field | Storage type | Spec shape / notes |
|---|---|---|
data_entered_by
|
FK → users.User
|
CASCADE, nullable. related_name="observations_entered". Write specs accept data_entered_by_id: int; read specs serialize a nested UserSpec
|
performer
|
JSONField (default {})
|
user), id: str }. Use it when the performer differs from the data-entry user |
Value
| Field | Storage type | Spec shape / notes |
|---|---|---|
value_type
|
CharField(255)
|
Enum QuestionType (from the questionnaire module). Tells the client how to read value — see the table below. Required in specs
|
value
|
JSONField
|
Spec: QuestionnaireSubmitResultValue { value?: str, unit?: Coding, coding?: Coding }. Required on create, optional on update. value holds the raw/string result, unit the quantity unit, coding the coded answer
|
note
|
TextField
|
None. Free-text note |
Clinical qualifiers
| Field | Storage type | Spec shape / notes |
|---|---|---|
body_site
|
JSONField (default {})
|
Spec: optional Coding bound to CARE_BODY_SITE_VALUESET (slug system-body-site-observation, SNOMED CT). FHIR Observation.bodySite
|
method
|
JSONField (default {})
|
Spec: optional Coding bound to CARE_OBSERVATION_COLLECTION_METHOD (slug system-collection-method, SNOMED CT). FHIR Observation.method
|
reference_range
|
JSONField (default [])
|
Spec: ReferenceRange[] (shape below), default []. Reference ranges for the value, usually carried over from the observation definition
|
interpretation
|
JSONField (default {})
|
Spec: free dict, default {}. Coded interpretation against the reference range (high/low/normal). Normal/abnormal/critical value sets exist (below) but are not enforced on this dict
|
interpretation_old
|
CharField(255)
|
Nullable. Legacy free-text interpretation, kept for backward compatibility. Not in the specs |
Structure & relationships
| Field | Storage type | Spec shape / notes |
|---|---|---|
parent
|
UUIDField
|
None — the external_id of a parent observation, for nesting related observations
|
component
|
JSONField (default [])
|
Spec: Component[] (shape below), default []. Sub-observations sharing this context but carrying their own codes and values (FHIR Observation.component)
|
questionnaire_response
|
FK → QuestionnaireResponse
|
None. The submission that produced this observation |
diagnostic_report
|
FK → DiagnosticReport
|
CASCADE, nullable. The report this observation belongs to, if any. Not in the write specs
|
observation_definition
|
FK → ObservationDefinition
|
CASCADE, nullable. The definition this observation templates from. Serialized as BaseObservationDefinitionSpec only in ObservationRetrieveSpec
|
Enum & value-set reference
ObservationStatus values
| Value | Meaning |
|---|---|
final
|
Recorded, complete and verified. The default for questionnaire-sourced observations |
amended
|
Was final, then corrected
|
entered_in_error
|
Recorded in error; disregard it |
PerformerType values (performer.type)
| Value |
|---|
related_person
|
user
|
SubjectType values (subject_type)
| Value |
|---|
patient
|
encounter (spec default)
|
QuestionType values (value_type)
From the questionnaire module. The value tells the client which key of value to read.
| Value | Value sourced from QuestionnaireSubmitResultValue
|
|---|---|
group
|
grouping node (no direct value) |
boolean
|
value ("true"/"false")
|
decimal
|
value
|
integer
|
value
|
string
|
value
|
text
|
value
|
display
|
display-only |
date
|
value
|
dateTime
|
value
|
time
|
value
|
choice
|
coding
|
url
|
value
|
quantity
|
value + unit
|
structured
|
structured payload |
Bound value sets
Coded fields validate against registered Care value sets. A body_site or method coding outside its value set is rejected during deserialization.
| Field | Value set | Slug | System(s) |
|---|---|---|---|
main_code
|
CARE_OBSERVATION_VALUSET
|
system-observation
|
http://loinc.org
|
body_site
|
CARE_BODY_SITE_VALUESET
|
system-body-site-observation
|
http://snomed.info/sct (curated concept list + descendants of 442083009)
|
method
|
CARE_OBSERVATION_COLLECTION_METHOD
|
system-collection-method
|
http://snomed.info/sct (descendants of 272394005, 129264002, 386053000)
|
These interpretation value sets are registered for the frontend and observation definitions, but are not enforced on the interpretation dict:
| Value set | Slug | Concepts (system http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation)
|
|---|---|---|
| Normal | system-normal-coded-valueset
|
N Normal, ND Not detected, NEG Negative
|
| Abnormal | system-abnormal-coded-valueset
|
A Abnormal, AA Critically abnormal, H High, HH Critically high, L Low, LL Critically low, POS Positive, DET Detected
|
| Critical | system-critical-coded-valueset
|
C Critical, CC Critical high, CL Critical low, CV Critical value
|
| UCUM units | system-ucum-units
|
http://unitsofmeasure.org (all UCUM units)
|
Nested JSON shapes (from the spec)
The structures behind the model's JSONFields.
Coding
Coding {
system: str | null # e.g. http://loinc.org
version: str | null
code: str # required
display: str | null
} # extra keys forbidden
CodeableConcept (alternate_coding)
CodeableConcept {
id: str | null
coding: Coding[] | null
text: str | null # field present, required key
} # extra keys forbidden
QuestionnaireSubmitResultValue (value)
QuestionnaireSubmitResultValue {
value: str | null # raw/string value
unit: Coding | null # for quantity values
coding: Coding | null # for coded values
}
Performer (performer)
Performer {
type: PerformerType # related_person | user
id: str
}
ReferenceRange (reference_range[])
ReferenceRange {
min: float | null
max: float | null
unit: str | null
interpretation: str # required
value: str | null
}
Component (component[])
Component {
value: QuestionnaireSubmitResultValue # required
interpretation: str | dict = {}
reference_range: ReferenceRange[] = []
code: Coding | null = null
note: str = ""
}
Resource specs (API schema)
The Pydantic specs build on [https://github.com/ohcnetwork/care/blob/develop/care/emr/resources/base.py EMRResource], which provides serialize / de_serialize and the perform_extra_serialization / perform_extra_deserialization hooks. Every concrete spec inherits from BaseObservationSpec.
| Spec | Role | Notes |
|---|---|---|
BaseObservationSpec
|
shared base | Defines the common fields: id, status, category, main_code, alternate_coding, subject_type, encounter, effective_datetime, performer, value_type, value, note, body_site (bound), method (bound), reference_range, interpretation, parent, questionnaire_response, component
|
ObservationSpec
|
write · create | Adds data_entered_by_id, created_by_id, updated_by_id (all int). Used internally when materializing observations from a questionnaire submission
|
ObservationUpdateSpec
|
write · update | The base, but effective_datetime and value relax to optional (None) for partial updates
|
ObservationReadSpec
|
read · list | Swaps the user IDs for nested created_by / updated_by / data_entered_by UserSpec objects
|
ObservationRetrieveSpec
|
read · detail | Extends ObservationReadSpec and additionally serializes observation_definition via BaseObservationDefinitionSpec when it is set
|
Server-side behaviour
ObservationSpec.perform_extra_deserialization(create/update): setsobj.external_id = self.id, copiesdata_entered_by_id,created_by_id,updated_by_idonto the model, dropsdata_entered_by_idfrommeta, and on create (is_updateis false) clearsobj.idso a new row is inserted.ObservationReadSpec.perform_extra_serialization: mapsidfromexternal_id; deliberately blanksencounter,patient, andquestionnaire_responsetoNonein the output to avoid extra DB queries; resolves the audit users (created_by,updated_by) anddata_entered_byfrom cache (model_from_cache).ObservationRetrieveSpec.perform_extra_serialization: calls the parent, then inlines the fullobservation_definitionwhen the FK is set.body_site/methodareValueSetBoundCoding[...]: the suppliedCodingis validated against its bound value set during deserialization and rejected if the code is not a member.de_serializeonly writes fields present in the model's column mapping. Non-default values are persisted (model_dump(exclude_defaults=True)), and unknown spec-only fields would land inmetawhen__store_metadata__is set — which, by default, it is not for observations.
Related models
Observation is self-contained; it expresses relationships through foreign keys rather than secondary tables.
patient → FK Patient (CASCADE)
encounter → FK Encounter (CASCADE)
data_entered_by → FK users.User (CASCADE, nullable)
questionnaire_response → FK QuestionnaireResponse (CASCADE, nullable)
diagnostic_report → FK DiagnosticReport (CASCADE, nullable)
observation_definition → FK ObservationDefinition (CASCADE, nullable)
parent is the exception: a soft, UUID-based self-reference to another observation's external_id, not a Django FK. It lets observations nest without a database constraint.
API integration notes
- Observations are exposed through Care's REST API and align with the FHIR
Observationresource. FHIR field names (effectiveDateTime,bodySite, and so on) differ from the Django model names; the resource specs above are the authoritative request/response schemas. - Most observations are created as a side effect of submitting a questionnaire.
valueandvalue_typemirror the submission types (QuestionnaireSubmitResultValue/QuestionType), andquestionnaire_responserecords provenance. effective_datetimemust be timezone-aware. Required on create, optional on update.statusis one offinal/amended/entered_in_error; questionnaire-sourced observations arefinal.body_siteandmethodare validated against their bound value sets, andmain_codeis expected to bind to LOINC viaCARE_OBSERVATION_VALUSET.- On read, the list and detail specs blank out
encounter,patient, andquestionnaire_response, so don't rely on those being populated in observation payloads. - Prefer structured observations. Allergy and medication checks read coded values, not free text, so unstructured data leaves them blind.
Source code
The files below are fetched live from the care repository — any changes pushed to the repo will show here automatically:
Model
Loading…
Spec
Loading…
Value set
Loading…
Related links
Related
Pages that link here:
- Reference: References/Base models & conventions
Wiki: ohcnwiki.tellmey.fyi