Creating an online multiple-choice questionnaire with Python

It takes less than an hour…

Kelvin Kramp
2 min readAug 15, 2021

There are many calculators online that are used to estimate the chance of medical harm due to disease such as risk calculators for thrombosis or mortality calculators for pneumonia. Most of them are made in Javascript and/or HTML. To see if and how Dash and Python can be used for making a medical calculator back and frontend I transformed the OPS assessment into an interactive form with multiple choice radio buttons. The code can be found on my GitHub and this is the link to the working version on Heroku.

In my example, I have used the OPS score. The OPS score is used to assess driving ability in the elderly. OPS stands for Orientation and memory, Practical skills and Social and personal functioning. It has been developed and published in 2000 by Frederiec Withaar from the University of Groningen in the article “Divided Attention and Driving, the effects of ageing and brain injury”. After the publication of her PhD thesis, the governmental organisation for medical drivers license checks in the Netherlands(CBR) started to ask for OPS scores of every applicant above the age of 75. There is currently no website that offers a quick calculation of the OPS score.

Steps

Creating a form adjusted to your needs will take you less than 60 minutes. You can use my code as a template. The main thing is to create a row with the dbc.Row function from Dash that contains a sentence and a row of labels with the answers displayed above radio buttons with the dcc.RadioItems function of Dash. The questions became a repeating pattern of the following:

dbc.Row(children=[
html.H5("Does the candidate overestimates her or his self concerning driving ability?",
style={"display": "inline-block", 'textAlign': 'center', "width": "50%", }),
dcc.RadioItems(
options=[
{'label': 'Yes', 'value': '1'},
{'label': 'Not sure', 'value': '2'},
{'label': 'No', 'value': '3'}
],
id='9',
value='',
# labelStyle={'display': 'inline-block', 'text-align': 'center','width': '100%'},
style={'display': 'inline-block', 'text-align': 'center', 'display': 'flex',
'justify-content': 'space-evenly', 'width': '30%'},
),
], ),

After a battery of rows the callback for the 9 questions looks as follows in its uncondensed form:

@app.callback(
Output('output-OPS-total', 'children'),
Output('output-O', 'children'),
Output('output-P', 'children'),
Output('output-S', 'children'),
[Input('1', 'value'),
Input('2', 'value'),
Input('3', 'value'),
Input('4', 'value'),
Input('5', 'value'),
Input('6', 'value'),
Input('7', 'value'),
Input('8', 'value'),
Input('9', 'value')])
def calc(Q1,Q2,Q3,Q4,Q5,Q6,Q7,Q8,Q9):
l = [Q1,Q2,Q3,Q4,Q5,Q6,Q7,Q8,Q9]
l_total, l_o, l_p, l_s = [], [], [], []
for i in l:
if i:
l_total.append(int(i))
for i in l[0:3]:
if i:
l_o.append(int(i))
for i in l[3:6]:
if i:
l_p.append(int(i))
for i in l[6:9]:
if i:
l_s.append(int(i))
return sum(l_total),sum(l_o),sum(l_p),sum(l_s)

After that created a Procfile with the following:

web: gunicorn OPS_calculator:server

and uploaded to Heroku:

git add .
git commit -m "update"
git push heroku master

The result looks something like this:

--

--