Backend
Backend responsibilities, models, API endpoints, and processing flow for Molecular.
Backend
Architecture Overview
The Molecular feature spans two backend repositories:
livehealthapp: owns the Gene, Antibiotic, and Organism master data APIs and their models under thereportingapp.crelio-app: owns report-entry persistence and the organism-antibiotic results summary API under thereportapp.
Master data is managed through REST APIs in livehealthapp. Report values are submitted and persisted through crelio-app. The two systems share the same master record identifiers (gene ids, antibiotic ids, organism ids) referenced at report entry.
System Design
Storage and Models
All core models live in livehealthapp/reporting/models/.
Gene
| Field | Type | Notes |
|---|---|---|
id | Auto PK | |
name | CharField (150) | Unique within a lab: unique_together = (("name", "lab"),) |
code | CharField (150) | Gene code |
gene_type | CharField (150) | Gene type classification |
cut_off | FloatField | Numeric cut-off; used by report-entry detection logic |
description | TextField | Optional |
cpt_code | CharField (250) | CPT billing code |
lab | ForeignKey to labs | Lab scope; null means system default |
is_disabled | BooleanField | Soft disable without deleting the record |
created_at / updated_at | DateTimeField | Auto-timestamps |
antibiotics (M2M) | via AntibioticResistance | Links genes to antibiotics through the resistance table |
db_table: Gene
Activity log categories: created = 537, updated = 538, enabled = 539, disabled = 540.
Antibiotic
| Field | Type | Notes |
|---|---|---|
id | Auto PK | |
name | CharField (150) | Unique within a lab |
category | CharField (200) | e.g., Fluoroquinolones, Third-generation cephalosporins |
code | CharField (150) | Antibiotic code; commonly an ATC code |
method | CharField (150) | Optional testing method |
unit | CharField (150) | Measurement unit |
device_name | CharField (100) | Optional device-specific name |
dosage | CharField (100) | Optional dosage |
description | TextField | Optional |
cpt_code | CharField (250) | CPT billing code |
sample_type | CharField (250) | Optional; constrained to defined sample type choices |
lab | ForeignKey to labs | Lab scope; null means system default |
is_disabled | BooleanField | Soft disable |
created_at / updated_at | DateTimeField | Auto-timestamps |
db_table: Antibiotic
Activity log categories: created = 432, updated = 433, enabled = 434, disabled = 435.
Valid report-entry fields: name, unit, method, code, dosage, category, device_name, description.
Organism
| Field | Type | Notes |
|---|---|---|
id | Auto PK | |
name | CharField (150) | Unique within a lab |
category | CharField (200) | Organism category |
code | CharField (150) | Organism code |
cut_off | FloatField | Numeric cut-off for detection logic |
description | TextField | Optional |
cpt_code | CharField (250) | CPT billing code |
sample_type | CharField (250) | Optional; constrained to defined sample type choices |
lab | ForeignKey to labs | Lab scope; null means system default |
is_disabled | BooleanField | Soft disable |
created_at / updated_at | DateTimeField | Auto-timestamps |
antibiotics (M2M) | via OrganismAntibiotics | Standard antibiogram mappings |
db_table: Organism
Activity log categories: created = 436, updated = 437, enabled = 438, disabled = 439.
Valid report-entry fields: name, result, cut_off, viral_load, interpration.
AntibioticResistance
Links a gene to an antibiotic. This is the through-table for the Gene ↔ Antibiotic M2M.
| Field | Type | Notes |
|---|---|---|
gene | ForeignKey → Gene | related_name = "gene_antibiotics" |
antibiotic | ForeignKey → Antibiotic | related_name = "antibiotic_gene" |
created_at / updated_at | DateTimeField | Auto-timestamps |
db_table: AntibioticResistance
After save, gene.update_cache() and antibiotic.update_cache() are called so the in-memory cache reflects the new mapping.
Bulk create deletes all existing gene-scoped mappings and recreates them in one pass, ensuring a clean state.
OrganismAntibiotics
Standard antibiogram junction table linking an organism to antibiotics.
| Field | Type | Notes |
|---|---|---|
organism | ForeignKey → Organism | |
antibiotic | ForeignKey → Antibiotic | related_name = "antibiotic_organisms" |
db_table: OrganismAntibiotics
MolecularOrganismAntibiotics
Molecular-specific antibiogram junction table linking an organism to antibiotics with ordering and active state.
| Field | Type | Notes |
|---|---|---|
id | AutoField PK | |
lab | ForeignKey → labs | |
organism | ForeignKey → Organism | |
antibiotic | ForeignKey → Antibiotic | |
is_active | BooleanField | Whether this mapping is currently active |
sequence | PositiveSmallIntegerField | Display ordering |
created_by | ForeignKey → labUser | related_name = "moa_created_by" |
updated_by | ForeignKey → labUser | related_name = "moa_updated_by" |
created_at / updated_at | BigIntegerField | Unix timestamps |
db_table: MolecularOrganismAntibiotics
When an organism is saved, save_molecular_antibiotic_mappings(...) is called. It bulk-updates existing mappings, bulk-creates new ones, and marks removed mappings as is_active = False. Records are never hard-deleted.
Core Backend Responsibilities
| Responsibility | App | View / Model | Notes |
|---|---|---|---|
| Gene CRUD | livehealthapp | GenesView | Create, list, retrieve, update |
| Gene enable / disable | livehealthapp | GenericEnableDisableView | Soft disable/enable |
| Antibiotic CRUD | livehealthapp | AntibioticsView | Create, list, retrieve, update |
| Antibiotic enable / disable | livehealthapp | AntibioticOrganismEnableDisableView | Soft disable/enable with model=Antibiotic |
| Organism CRUD | livehealthapp | OrganismsView | Create, list, retrieve, update |
| Organism enable / disable | livehealthapp | AntibioticOrganismEnableDisableView | Soft disable/enable with model=Organism |
| Organism ↔ Antibiotic mapping fetch | livehealthapp | OrganismAntibioticView | Bidirectional mapping retrieval |
| Gene cache update | livehealthapp | Gene.update_cache() | Called after save and after AntibioticResistance bulk create |
| Organism cache update | livehealthapp | Organism.update_cache() | Called after save; also invalidates gene cache via update_gene_cache() |
| Molecular organism antibiotic mapping | livehealthapp | Organism.save_molecular_antibiotic_mappings() | Upserts MolecularOrganismAntibiotics records during organism save |
| Report value persistence | crelio-app | DrugReportValuesUpdateView at report/<int:report_id>/drugs/update | Generic report-entry save used for molecular component values |
| Organism antibiotic summary | crelio-app | OrganismAntibioticSummaryView at report/organism-antibiotic-results/ | Produces antimicrobiogram summary from report values |
| Organism antibiotic summary repair | crelio-app | OrganismAntibioticSummaryRepairView at report/organism-antibiotic-summary/repair/ | Repairs inconsistent antimicrobiogram records |
| Device gene mapping | livehealthapp | device_gene_mapping | GET/POST/DELETE device-to-gene mappings for instrument integration |
| Device organism mapping | livehealthapp | device_organism_mapping | GET/POST/DELETE device-to-organism mappings for instrument integration |
Runtime Engine / Processing Flow
Gene master save flow
Organism save flow
Antibiotic disable flow
Gene cache invalidation cascade
Whenever a gene is saved, enabled, or disabled, Gene.update_organism_cache() fetches one organism belonging to the same lab and calls organism.update_cache(). This ensures that organism serializations that embed gene-mapping data are refreshed whenever genes change.
Conversely, when an organism is saved, Organism.update_gene_cache() fetches one gene in the same lab and calls gene.update_cache(), refreshing gene serializations that embed organism-mapping data.
Organism antibiotic results (antimicrobiogram)
Source: crelio-app/report/views/organism_antibiotic_summary.py
OrganismAntibioticSummaryView at report/organism-antibiotic-results/ receives molecular report values and builds the organism-antibiotic result matrix from submitted report data. This is the backend powering the antimicrobiogram display in the Antibiotic Resistance component's result view.
Report value persistence
Source: crelio-app/report/views/drug_report_values.py
DrugReportValuesUpdateView at report/<int:report_id>/drugs/update and report/<int:report_id>/drugs/default receives and persists molecular component values (Gene results, Organism results, Antibiotic Resistance values) in the same way toxicology drug report values are persisted. Molecular component payloads share this generic endpoint.
API / URL Touchpoints
All molecular master data APIs are mounted under /reporting/ in livehealthapp.
Gene endpoints
| Method | Endpoint | View | Action |
|---|---|---|---|
| GET | /reporting/genes/ | GenesView | List active genes |
| GET | /reporting/genes/?is_disabled=0 | GenesView | List active genes (frontend initial load) |
| GET | /reporting/genes/?is_disabled=1 | GenesView | List disabled genes |
| GET | /reporting/genes/{gene_id} | GenesView | Fetch single gene |
| POST | /reporting/genes/new/ | GenesView(is_new=True) | Create gene |
| POST | /reporting/genes/{gene_id}/update/ | GenesView | Update gene |
| POST | /reporting/genes/{instance_id}/disable/ | GenericEnableDisableView(disable=True, ModelClass=Gene) | Disable gene |
| POST | /reporting/genes/{instance_id}/enable/ | GenericEnableDisableView(disable=False, ModelClass=Gene) | Enable gene |
Antibiotic endpoints
| Method | Endpoint | View | Action |
|---|---|---|---|
| GET | /reporting/antibiotics/ | AntibioticsView | List active antibiotics |
| GET | /reporting/antibiotics/?is_disabled=0 | AntibioticsView | List active antibiotics (frontend initial load) |
| GET | /reporting/antibiotics/?is_disabled=1 | AntibioticsView | List disabled antibiotics |
| GET | /reporting/antibiotics/{antibiotic_id} | AntibioticsView | Fetch single antibiotic |
| POST | /reporting/antibiotics/new/ | AntibioticsView(is_new=True) | Create antibiotic |
| POST | /reporting/antibiotics/{antibiotic_id}/update/ | AntibioticsView | Update antibiotic |
| POST | /reporting/antibiotics/{instance_id}/disable/ | AntibioticOrganismEnableDisableView(should_disable=True, model=Antibiotic) | Disable antibiotic |
| POST | /reporting/antibiotics/{instance_id}/enable/ | AntibioticOrganismEnableDisableView(should_disable=False, model=Antibiotic) | Enable antibiotic |
| GET | /reporting/antibiotics/{instance_id}/organisms/ | OrganismAntibioticView(driver="antibiotic") | Fetch organisms linked to an antibiotic |
Organism endpoints
| Method | Endpoint | View | Action |
|---|---|---|---|
| GET | /reporting/organisms/ | OrganismsView | List active organisms |
| GET | /reporting/organisms/?is_disabled=0 | OrganismsView | List active organisms (frontend initial load) |
| GET | /reporting/organisms/?is_disabled=1 | OrganismsView | List disabled organisms |
| GET | /reporting/organisms/{organism_id} | OrganismsView | Fetch single organism |
| POST | /reporting/organisms/new/ | OrganismsView(is_new=True) | Create organism |
| POST | /reporting/organisms/{organism_id}/update/ | OrganismsView | Update organism |
| POST | /reporting/organisms/{instance_id}/disable/ | AntibioticOrganismEnableDisableView(should_disable=True, model=Organism) | Disable organism |
| POST | /reporting/organisms/{instance_id}/enable/ | AntibioticOrganismEnableDisableView(should_disable=False, model=Organism) | Enable organism |
| GET | /reporting/organisms/{instance_id}/antibiotics/ | OrganismAntibioticView(driver="organism") | Fetch antibiotics linked to an organism |
Device mapping endpoints
| Method | Endpoint | View | Action |
|---|---|---|---|
| GET | (device molecular URL) | device_gene_mapping | Fetch device-to-gene mappings |
| POST | (device molecular URL) | device_gene_mapping | Create device-to-gene mappings |
| DELETE | (device molecular URL) | device_gene_mapping | Delete device-to-gene mappings |
| GET | (device molecular URL) | device_organism_mapping | Fetch device-to-organism mappings |
| POST | (device molecular URL) | device_organism_mapping | Create device-to-organism mappings |
| DELETE | (device molecular URL) | device_organism_mapping | Delete device-to-organism mappings |
crelio-app report endpoints
| Method | Endpoint | View | Action |
|---|---|---|---|
| POST | report/<int:report_id>/drugs/update | DrugReportValuesUpdateView | Persist molecular component report values at report entry |
| POST | report/<int:report_id>/drugs/default | DrugReportValuesUpdateView | Apply default molecular values |
| POST | report/organism-antibiotic-results/ | OrganismAntibioticSummaryView | Build and persist organism-antibiotic result summary |
| GET | report/organism-antibiotic-summary/repair/ | OrganismAntibioticSummaryRepairView | Repair inconsistent antimicrobiogram data |
Entity Creation and Side Effects
| Action | Side effects |
|---|---|
| Create gene | AntibioticResistance.bulk_create() saves gene-antibiotic mappings; activity log added; organism cache cleared; gene cache cleared |
| Update gene | Same as create; existing AntibioticResistance mappings for the gene are deleted and recreated |
| Disable gene | Activity log added; organism cache cleared; gene cache cleared; no mapping deletion |
| Enable gene | Activity log added; organism cache cleared; gene cache cleared |
| Create antibiotic | OrganismAntibiotics.bulk_create() saves organism mappings; activity log added; antibiotic cache cleared |
| Update antibiotic | Same as create; existing organism mappings for the antibiotic are deleted and recreated |
| Disable antibiotic | All OrganismAntibiotics for this antibiotic are cleared (empty mapping list); activity log added; cache cleared |
| Enable antibiotic | No mapping change (after_save returns early on enabled); activity log added; cache cleared |
| Create organism | OrganismAntibiotics.bulk_create() saves antibiotic mappings; save_molecular_antibiotic_mappings() upserts MolecularOrganismAntibiotics; activity log added; organism and gene caches cleared |
| Update organism | Same as create |
| Disable organism | Same mapping clear flow as create; activity log added; organism and gene caches cleared |
| Enable organism | No mapping change (after_save returns early on enabled); activity log added; cache cleared |