Handlers
When a user selects an existing item from the MaRDI Portal or Wikidata in a questionnaire field, MaRDMO automatically retrieves and fills in all associated metadata — labels, descriptions, relations, and linked sub-entities — without any manual copying. This is the job of the handlers.
Signal Wiring
RDMO emits a value_created or value_updated signal every time a questionnaire answer is saved by the user. MaRDMO registers signal receivers in router.py.
At startup, build_handler_map() constructs a nested lookup table:
{ catalog_uri: { attribute_uri: handler_method } }
On each incoming signal the router checks the active catalog and the URI of the saved attribute, and dispatches to the matching handler method. A separate DELETE_HANDLER_MAP handles cleanup when a value is removed: it deletes all dependent answers that were previously filled in for that entity.
Why Not Django Signals for the Cascade?
value_editor() — the helper that writes answers back into the project — saves values directly to the database. If these writes triggered Django signals, every programmatic fill would re-activate handlers, creating runaway cascades.
More critically, during an RDMO project import all values are written to the database in bulk while Django signals are already active. Using signals for the fill cascade would cause handlers to fire out of order against a partially-loaded project, producing incomplete or corrupt results. MaRDMO therefore uses direct function calls for all handler-to-handler cascading, ensuring that fills only happen in response to genuine user interactions.
Handler Flow
The sequence when a user picks a Mathematical Model from the portal:
- RDMO emits
value_created/value_updatedfor the model ID field. - The router dispatches to
Information.model(instance). model()calls_entry(), which collects the selected QID and calls_fill_model_batch()._fetch_by_source()fires a single SPARQL query (against MaRDI Portal, and optionally Wikidata) to retrieve the model's metadata._fill_model_batch()writes labels, descriptions, aliases, properties, and relations into the appropriate questionnaire pages viavalue_editor().- For each related sub-entity type (Research Problems, Mathematical Formulations, Computational Tasks, …),
_fill_model_batch()calls_hydrate_relatants(), which in turn calls the corresponding_fill_*_batch()method directly — no signal is emitted. - Each
_fill_*_batch()call batches its SPARQL query across all entities of that type at once. For example, if the selected model contains ten Mathematical Formulations, all ten are fetched in a single query and then distributed across the ten questionnaire pages. The same applies to linked Research Problems, Computational Tasks, and so on. - A
visitedset is passed through the entire call tree to prevent infinite loops when entities reference each other cyclically.
The batching principle ensures that the number of SPARQL queries scales with the number of distinct entity types in the cascade, not with the number of individual entities.