Questionnaire

Introduction #

The Questionnaire model represents a structured set of questions intended to guide the collection of answers from end-users.

The Interview model represents answers to a structured set of questions represented by a Questionnaire.

Basic usage #

To get a questionnaire or interview by identifier, use the get method on the Questionnaire or Interview model managers:

from canvas_sdk.v1.data.questionnaire import Interview, Questionnaire

questionnaire = Questionnaire.objects.get(id="b80b1cdc-2e6a-4aca-90cc-ebc02e683f35")
interview = Interview.objects.get(id="75df6d7f-d58d-443b-9fa0-ce43b4d7b2a0")

If you have a patient object, the interviews for a patient can be accessed with the interviews attribute on a Patient object:

from canvas_sdk.v1.data.patient import Patient

patient = Patient.objects.get(id="1eed3ea2a8d546a1b681a2a45de1d790")
interviews = patient.interviews.all()

If you have a patient ID, you can get the interviews for the patient with the for_patient method on the Interview model manager:

from canvas_sdk.v1.data.questionnaire import Interview

patient_id = "1eed3ea2a8d546a1b681a2a45de1d790"
interviews = Interview.objects.for_patient(patient_id)

Questionnaire questions #

The questions for a questionnaire can be accessed with the questions attribute on an Questionnaire object:

from canvas_sdk.v1.data.questionnaire import Questionnaire
from logger import log

questionnaire = Questionnaire.objects.get(id="b80b1cdc-2e6a-4aca-90cc-ebc02e683f35")

for question in questionnaire.questions.all():
    log.info(f"system: {question.code_system}")
    log.info(f"code: {question.code}")
    log.info(f"name: {question.name}")

Interview responses #

The interview responses for an interview can be accessed with the interview_responses attribute on an Interview object:

from canvas_sdk.v1.data.questionnaire import Interview
from logger import log

interview = Interview.objects.get(id="75df6d7f-d58d-443b-9fa0-ce43b4d7b2a0")

for interview_response in interview.interview_responses.all():
    log.info(f"response option: {interview_response.response_option_value}")

Filtering #

Questionnaires and interviews can be filtered by any attribute that exists on the models.

Filtering for questionnaires and interviews is done with the filter method on the Questionnaire and Interview model managers.

By attribute #

Specify an attribute with filter to filter by that attribute:

from canvas_sdk.v1.data.questionnaire import Interview, Questionnaire

questionnaires = Questionnaire.objects.filter(name="Tobacco")
interviews = Interview.objects.filter(progress_status="F")

By ValueSet #

See Value Sets for the library of built-in value sets and how to create your own.

Filtering by ValueSet works a little differently. The find method on the model manager is used to perform ValueSet filtering:

from canvas_sdk.v1.data.questionnaire import Questionnaire
from canvas_sdk.value_set.v2022.assessment import TobaccoUseScreening

questionnaires = Questionnaire.objects.find(TobaccoUseScreening)

Interview also supports find, which returns the interviews whose questionnaire has a code in the value set:

from canvas_sdk.v1.data.questionnaire import Interview
from canvas_sdk.value_set.v2022.assessment import TobaccoUseScreening

interviews = Interview.objects.find(TobaccoUseScreening)

For interviews, find matches against the related Questionnaire through the questionnaires relation. Questionnaires store their code system by name (for example, "LOINC") rather than by URL, and find handles this for you. It also composes with for_patient:

from canvas_sdk.v1.data.questionnaire import Interview
from canvas_sdk.value_set.v2022.assessment import TobaccoUseScreening

interviews = (
    Interview.objects
    .for_patient("1eed3ea2a8d546a1b681a2a45de1d790")
    .find(TobaccoUseScreening)
)

Attributes #

ResponseOptionSet #

Field NameType
dbidInteger
createdDateTime
modifiedDateTime
statusString
nameString
code_systemString
codeString
typeString — one of the question types below
use_in_shxBoolean
optionsResponseOption[]
questionsQuestion[]

Question types #

type holds the code for the kind of question the option set describes. It decides how the question renders in a note and which value an answer carries.

typeQuestionAnswer
TXTFree textText, on the response’s response_option_value.
INTIntegerA whole number.
DECDecimalA decimal number.
DATEDateA calendar date, on the response’s response_option_date.
SINGSingle selectOne ResponseOption.
MULTMulti selectOne or more ResponseOption records.

TXT and DATE questions are not scored, so they are skipped when a questionnaire calculates a score. Authoring a questionnaire in a plugin sets this through the question’s responses_type — see Response types.

ResponseOption #

Field NameType
dbidInteger
createdDateTime
modifiedDateTime
statusString
nameString
codeString
code_descriptionString
valueString
response_option_setResponseOptionSet
orderingInteger
interview_responsesInterviewQuestionResponse[]
enablement_conditionsQuestionEnablementCondition[]

enablement_conditions holds the conditions that test for this response option, which is how you find the questions a given answer unlocks.

Question #

Field NameType
idUUID
dbidInteger
createdDateTime
modifiedDateTime
statusString
nameString
response_option_setResponseOptionSet
acknowledge_onlyBoolean
show_prologueBoolean
code_systemString
codeString
enable_behaviorString — all or any
interview_responsesInterviewQuestionResponse[]
dependent_conditionsQuestionEnablementCondition[]
triggers_conditionQuestionEnablementCondition[]

enable_behavior decides whether all of the question’s enablement conditions must be met for it to be enabled, or only one of them. It is empty on a question authored without an enabled_behavior, so handle an empty value when reading it.

The read-side attribute here is enable_behavior (no “d”). When authoring a questionnaire through the effect or the manifest schema, the matching config field is spelled enabled_behavior (with a “d”). The difference is intentional.

A question sits on both sides of the branching, so it carries a relation for each direction:

  • dependent_conditions: the conditions that decide whether this question is enabled.
  • triggers_condition: the conditions on other questions that test this question’s answer.

QuestionEnablementCondition #

A QuestionEnablementCondition controls when a Question is enabled, following FHIR’s enableWhen pattern. Import it with from canvas_sdk.v1.data import QuestionEnablementCondition. Here question is the question the condition governs, and dependent_on is the question whose answer is tested.

Field NameType
dbidInteger
createdDateTime
modifiedDateTime
statusString
questionQuestion
dependent_onQuestion
operatorString — =, !=, exists, or not_exists
answer_optionResponseOption
answer_valueString

operator takes the same comparison operators as a questionnaire’s enabled conditions (see Enablement operators). answer_option references the ResponseOption matched, the read-side counterpart of a condition’s value_code; answer_value holds a literal value matched, the counterpart of a condition’s value_string.

Questionnaire #

Field NameType
idUUID
dbidInteger
createdDateTime
modifiedDateTime
statusString
nameString
expected_completion_timeFloat
can_originate_in_chartingBoolean
use_case_in_chartingString
scoring_function_nameString
scoring_code_systemString
scoring_codeString
code_systemString
codeString
search_tagsString
questionsQuestion[]
use_in_shxBoolean
carry_forwardString
interview_responsesInterviewQuestionResponse[]

QuestionnaireQuestionMap #

Field NameType
dbidInteger
createdDateTime
modifiedDateTime
statusString
questionnaireQuestionnaire
questionQuestion

Interview #

Field NameType
idUUID
dbidInteger
committerCanvasUser
entered_in_errorCanvasUser
statusString
nameString
language_idInteger
use_case_in_chartingString
patientPatient
note_idInteger
appointment_idInteger
questionnairesQuestionnaire[]
progress_statusString
createdDateTime
modifiedDateTime
interview_responsesInterviewQuestionResponse[]
assessment_setAssessment[]

InterviewQuestionnaireMap #

The join between an Interview and the questionnaires it covers. Reach them through the interview’s questionnaires attribute rather than querying this model.

Field NameType
dbidInteger
createdDateTime
modifiedDateTime
statusString
interviewInterview
questionnaireQuestionnaire

InterviewQuestionResponse #

Field NameType
dbidInteger
createdDateTime
modifiedDateTime
statusString
interviewInterview
questionnaireQuestionnaire
questionQuestion
response_optionResponseOption
response_option_valueString
response_option_dateDate
questionnaire_stateString
interview_stateString
commentString