OPAL Patient List views
OPAL provides support for displaying lists of patients, both via a spreadsheet like view, and with a card based view.
Defining lists
OPAL patient lists are subclasses of opal.core.patient_lists.PatientList
.
Typically these are found in a patient_lists.py
module of your application or plugin. (Lists can be
defined elsewhere, but may not be autodiscovered.)
A basic list needs only define it's display_name
a queryset
of episodes to display, and
a schema
of subrecords to show for each episode.
# patient_lists.py
from opal.models import Episore
from opal.core import patient_lists
from myapplication import models
class AlphabetListA(patient_lists.PatientList):
display_name = 'A Patients'
queryset = Episode.objects.filter(demographics__name__istartswith='a')
schema = [
models.Demographics,
models.Location,
models.Diagnosis,
models.Treatment
]
The display_name
property is the human readable name for our list - which is displayed as
link text to our list.
Schemas
Schemas are lists of Subrecords that we would like to display in our list. By default we render the subrecord display_template, and allow editing and addition of each subrecord in place.
Template selection
The list view is constructed by rendering a column for each record, in the order defined in the schema, and a row for each episode in the list.
The template for each cell should live in ./templates/records/*
. In order to
select the appropriate template for a given episode, OPAL looks in the following
locations:
records/{episode_type}/{list slug}/{record_name}.html
records/{list_slug}/{record_name}.html
records/{episode_type}/{record_name}.html
records/{record_name}.html
Querysets
The queryset property of your list should contain all of the episodes for this particular
list. On occasion we require a more dynamic queryset, in which case we can ovreride the
get_queryset
method.
# patient_lists.py
import datetime
from opal.models import Episode
from opal.core import patient_lists
class MyWeeklyList(patient_lists.PatientList):
def get_queryset(self):
one_week_ago = datetime.date.today() - datetime.timedelta(days=1)
return Episode.objects.filter(date_of_admission__gte=one_week_ago)
Ordering Lists
As a discoverable.SortableFeature lists may be ordered by setting the
order
property to an integer. Lists will display in drop-downs, tables et cetera, in
this order.
Slug
As a discoverable feature, the slug for each list is determined by
either setting the slug
property, or returning a string from the get_slug
classmethod.
Templates
Tagged Patient Lists
A common model for working with lists is to use lists based on the tags assigned to an episode. This allows users to add and remove patients from lists as they see fit, rather than attempting to infer it from other properties of the patient (e.g. their current location for instance.) which can be particularly challenging for some clinical services.
OPAL provides a specific subclass for working with Tagged Patient Lists:
# patient_lists.py
from opal.core import patient_lists
class MyTagList(patient_lists.TaggedPatientList):
display_name = 'Tagged blue'
tag = 'blue'
Tagged lists will automatically fetch the appropriate queryset for patients tagged with the tag you specify.
Invalid Tagged Patient Lists
Tag names may not have hyphens in them - OPAL uses hyphens to distinguish between tags and subtags in the urls for lists, so attempting to define one will raise an exception.
class MyList(TaggedPatientList):
tag = 'foo-bar'
# This will raise InvalidDiscoverableFeatureError !
Direct Add
Sometimes, we want to control the flow of patients onto, off, or between lists a little more closely. For instance, we might need to ensure additional data collection at points in a patient journey.
In order to accomplish this, we often implement custom patient flows that wil programatically tag
episodes to tagged lists. In those cases we will want to prevent users from manually adding or
removing the tags themselves. This can be easily accomplished via the direct_add
property. When
set to false, users will not be able to add the tag for this list.
class MyLockedDownList(TaggedPatientList):
tag = 'liaisonpatients'
direct_add = False
Access Control
As PatientLists are a RestrictableFeature, Access control
for lists is set by overriding the visible_to
classmethod. Your list will only be visible to
those users for whom this method returns True
.
For instance, we could define a Patient List that was only available to Django Superusers:
class SuperuserPatientList(PatientList):
@classmethod
def visible_to(klass, user):
return user.is_superuser