Reference data
Lookup Lists allow us to create or reference canonical lists of available terminology as a foreign key, while also allowing synonymous terms, and a free text override.
Core referencedata
By default, Opal will install some lookuplists for common things such as countries, drugs,
conditions, and symptoms amongst others. The data for these is found in the
opal.core.referencedata
package.
Adding a lookup list
Lookup lists are subclasses of opal.core.lookuplists.LookupList
. Typically, a specific named
lookup list will not need to do anything other than define a class that inherits from the base
class.
The custom field type opal.core.fields.ForeignKeyOrFreeText
allows you to build interfaces
that cater for synonyms, and also allow the user to enter a free text string that is not in
the lookup list.
# yourapp.models
from django.db import models
from opal.core import lookuplists
from opal.core.fields import ForeignKeyOrFreeText
from opal.models import EpisodeSubrecord
class TreatmentType(lookuplists.LookupList): pass
class Treatment(EpisodeSubrecord):
treatment = ForeignKeyOrFreeText(TreatmentType)
notes = models.CharField(max_length=200)
When you create your lookup list, you are creating a new model, so you will need a new migration to accompany it.
$ python manage.py schemamigration --atuo yourapp
$ python manage.py migrate yourapp
The lookup list will automatically be added to the admin, where you can manually add entries.
Reference data JSON API
Reference data is available over the Opal JSON API.
You may either load all lookuplists at once via the /api/v0.1/referencedata/
endpoint, or
individual lookuplists by name - for example all diagnoses from /api/v0.1/referencedata/diagnosis/
.
The reference data API also loads all synonyms in a flat list - the conversion of synonyms to their
canonical form is handled by the save mechanism of subrecords using ForeignKeyOrFreeText
fields.
Working with reference data on the front end
The Angular service Referencedata
can be used to fetch all lookuplists at once - for instance
loaded in the Angular routing for a controller in your application
when('/my/route', {
controller: 'MyCtrl',
resolve: {
referencedata: function(Referencedata){ return Referencedata; }
}
}
Lookuplists will then be available either as properties of the referencedata
object.
Using referencedata in forms
The Opal form templatetag library allow us to easily incorporate
referencedata into the forms we build, either by detecting their use automatically when we have
ForeignKeyOrFreeText
fields, or explicitly by passing an argument.
{% load forms %}
{% input field="Diagnosis.condition" %}
{% select label="List of Conditions" lookuplist="referencedata.diagnosis" %}
Providing data for lookuplists
Reference data can be provided at application or plugin level in a file named lookuplists.json
found in the
{{ app_or_plugin }}/data/lookuplists
directory. This data should be in the Opal JSON format. The name value
of each lookuplist should be the return value of that lookuplist's get_api_name()
method (otherwise they
will fail to load), these can be found via Schemas
{
"name_of_lookuplist": [
{
"name": "Value of lookuplist item",
"synonyms": ["Synonym 1",]
},
]
}
Once this data is stored in the lookuplists file, we can batch load it into our application with the command
python manage.py load_lookup_lists
Coding lookuplist values
Often applications wish to use coded reference data from a pre-existing terminology such as SNOMED.
This can be easily accomplished by adding coding values to the lookuplist JSON data.
{
"name_of_lookuplist": [
{
"name": "Value of lookuplist item",
"synonyms": ["Synonym 1",],
"coding": {
"system": "SNOMED CT",
"code": "3428473"
}
},
]
}
Management commands
Opal ships with some management commands for importing and exporting lookup lists
dump_lookup_lists
Prints all loockuplists as JSON to stdout.
When the --many-files
argument is passd, the command will write each installed
lookup list to a separate file in the ./data/lookuplists
directory of the
application.
load_lookup_lists
Loads lookup lists from all plugins/apps in the Opal JSON format. The lookup
lists are expected to be in {{ app }}/data/lookuplists/lookuplists.json
Optionally you can pass in an explicit filename with the -f
argument.
delete_all_lookup_lists
Deletes all currently lookuplist values and related synonyms