Creating an online multiple-choice questionnaire with Python

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.


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:

html.H5("Does the candidate overestimates her or his self concerning driving ability?",
style={"display": "inline-block", 'textAlign': 'center', "width": "50%", }),
{'label': 'Yes', 'value': '1'},
{'label': 'Not sure', 'value': '2'},
{'label': 'No', 'value': '3'}
# 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:

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:
for i in l[0:3]:
if i:
for i in l[3:6]:
if i:
for i in l[6:9]:
if 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:

MD, PhD, Python programming enthusiast,

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Localization vs Internationalization

Getters and Setters in Kotlin

Automated work progress tracking

[Leet Code] Merge Strings Alternately

Sharing is Caring! Domain objects in BOTH Scala and R with GraalVM Polyglot bindings.

Dipping A Toe into Open Source

Netlify for the frontend, Micro for the backend

CS373 Week of 1 Feb — 7 Feb

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Kelvin Kramp

Kelvin Kramp

MD, PhD, Python programming enthusiast,

More from Medium

Create a data scraper in Python

Data scraping with Scrapy and Excel

FastAPI — The Complete Course 2022 (Beginner + Advanced)

FastAPI – The Complete Course 2022 (Beginner + Advanced)

How to connect to an API with Python