You are on page 1of 81

QCAT Documentation

Release 0.1.0

Lukas Vonlanthen (CDE)

Feb 08, 2018


Contents

1 Glossary 3

2 Setup 5
2.1 Installation and Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

3 Configuration 9
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2 Questionnaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.3 Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4 Development 43
4.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.2 Data Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.3 Data Format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.4 Elasticsearch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.5 Data flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.6 User Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.7 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.8 Translations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.9 Deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.10 Django Snippets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.11 Grunt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

5 Contributions 59
5.1 Translations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

6 API 61
6.1 API Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

7 Hosting 69
7.1 Hosting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
7.2 Latest changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
7.3 Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

8 Indices and tables 75


8.1 To Do’s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

i
ii
QCAT Documentation, Release 0.1.0

Contents:

Contents 1
QCAT Documentation, Release 0.1.0

2 Contents
CHAPTER 1

Glossary

User Group
User Groups A User Group within the context of QCAT is a group of user sharing the same permissions. See User
Groups for more information.
WOCAT WOCAT is the World Overview of Conservation Approaches and Technologies, an established global
network of Soil and Water Conservation (SWC) specialists, dedicated to sustainable land management.
Please refer to http://www.wocat.net for more information.

3
QCAT Documentation, Release 0.1.0

4 Chapter 1. Glossary
CHAPTER 2

Setup

2.1 Installation and Setup

2.1.1 Requirements

The qcat application needs a whole range of server applications:


• Apache webserver
• Postgresql >= 9.4 with postgis extension
• uwsgi: application server for python web applications together
• elasticsearch: search engine based on Lucene
• memcached: Memory caching

Postgresql

Postgresql 9.4 or bigger is needed as JSONP is used. Postgis 2.1 or bigger is needed as well.

uwsgi

uwsgi is needed at least in version 2.x or bigger. In the following explanations we use uwsgi in emperor mode.
Furthermore uwsgi needs the python3 plugin and apache needs the uwsgi-proxy module:
apt-get install uwsgi-emperor uwsgi-plugin-python3 libapache2-mod-proxy-uwsgi

Other required packages

sudo apt-get install python3-pip python3-psycopg2 libpg-dev python3-pil memcached


˓→libmemcached-dev nodejs nodejs-legacy npm

5
QCAT Documentation, Release 0.1.0

wkhtmltopdf: a version with patched QT is required. Get the current stable version at http://wkhtmltopdf.org/
downloads.html

cd /tmp
wget <download_file>
sudo tar xvf wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
sudo mv wkhtmltox/bin/wkhtmlto* /usr/bin

2.1.2 Installation

Backend installation

1. Creating user ‘qcat’:

sudo adduser qcat && addgroup qcat:qcat

2. Create the application folder:

sudo mkdir qcat-live


chown qcat:qcat qcat-live

3. Install virtualenv:

sudo pip3 install virtualenv

4. Now change privileges to user ‘qcat’:

sudo -u qcat -i
cd qcat-live

5. Get the application from the github repository:

git clone https://github.com/CDE-UNIBE/qcat.git source

6. Create virtualenv and activate it:

virtualenv -p python3 virtualenv


source virtualenv/bin/activate

7. Install all requirements python requirements for the application:

cd source
pip3 install -r requirements/production.txt

8. Now we are ready to install the system based stuff. This is done with fabric from another computer:

fab deploy_demo

9. Now we can try, if the Django applicatio is valid:

cd qcat-live/source
python3 manage.py validate

6 Chapter 2. Setup
QCAT Documentation, Release 0.1.0

Frontend installation

1. Change to project folder and use NPM to install Bower and Grunt:

cd qcat-live/source
npm install -g grunt-cli bower

2. Install the project dependencies:

npm install

3. Change to qcat user and let Bower collect the required libraries:

bower install

4. Use Grunt to build the static files:

grunt build

2.1. Installation and Setup 7


QCAT Documentation, Release 0.1.0

8 Chapter 2. Setup
CHAPTER 3

Configuration

3.1 Introduction

3.1.1 Settings

Please refer to the Application settings of QCAT.

3.1.2 Questionnaires

A questionnaire consists of several objects which themselves can have multiple child objects. This represents the
hierarchy of the questionnaire.
The elements of a Questionnaire are:
1. Questionnaire: The top node of the questionnaire, represents the entire questionnaire.
2. Category: A (thematic) group, corresponds to a single step in the questionnaire form.
3. Subcategory: Another element for grouping inside the category.
4. Questiongroup: A group of questions which belong together.
5. Question: A single question consisting of a key and value(s).
6. Key: The key of a question.
7. Value: The value of a question.
8. Links: Links to other questionnaires.
Most of the elements of a questionnaire can have a configuration of their own, stored in their configuration field
in the database. However, some of the elements allow overwriting part of their configuration in the Questionnaire
configuration.
The following table indicates which objects allow configuration in the database and which can have their configuration
defined or overwritten in the Questionnaire configuration.

9
QCAT Documentation, Release 0.1.0

Configuration in DB In Questionnaire
Category No Yes
Subcategory No Yes
Questiongroup Yes Yes
Question No Yes (only in questionnaire configuration)
Key Yes No
Value Yes No

Todo: Questionnaire configurations can inherit from another one. This needs further documentation.

3.2 Questionnaires

3.2.1 Questionnaire Configuration

Contains the configuration of an entire questionnaire. It allows to overwrite certain default configurations of its child
elements.
The configuration of a Questionnaire is stored in a JSON format in the configuration field of
configuration.models.Configuration.
See also:
configuration.configuration.QuestionnaireConfiguration

Parent element: (None)


Child element: Category Configuration

Format

The basic format of the configuration is as follows:


{
# See class QuestionnaireSection for the format of sections.
"sections": [
{
# See class QuestionnaireCategory for the format of categories.
"categories": [
{
# The keyword of the category.
"keyword": "CAT_KEYWORD",

# See class QuestionnaireSubcategory for the format of subcategories.


"subcategories": [
{
# The keyword of the subcategory.
"keyword": "SUBCAT_KEYWORD",

# See class QuestionnaireQuestiongroup for the format of


# questiongroups.
"questiongroups": [
{

10 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

# The keyword of the questiongroup.


"keyword": "QUESTIONGROUP_KEYWORD",

# (optional)
"template": "TEMPLATE_NAME",

# (optional)
"min_num": 1,

# (optional)
"max_num": 1,

# See class QuestionnaireQuestion for the format of questions.


"questions": [
{
# The key of the question.
"key": "KEY"
}
]
}
]
}
]
}
]
}
]
}

See also:
For more information on the configuration of its child elements, please refer to their respective documentation:
• Category Configuration
• Subcategory Configuration
• Questiongroup Configuration
• Question Configuration
• Key Configuration
• Value Configuration

sections

A list of Section Configuration.

links

A dictionary with the configuration of the links which are possible from this questionnaire. Please note that only
base_configurations should be linked.

Example

The following is an arbitrary example of how a configuration could look like:

3.2. Questionnaires 11
QCAT Documentation, Release 0.1.0

{
"sections": [
{
"keyword": "section_1",
"categories": [
{
"keyword": "cat_0",
"subcategories": [
{
"keyword": "subcat_0_1",
"questiongroups": [
{
"keyword": "qg_14",
"questions": [
{
"keyword": "key_19",
"in_list": true
}
]
},
{
"keyword": "qg_15",
"questions": [
{
"keyword": "key_20"
}
]
}
]
}
]
},
{
"keyword": "cat_1",
"subcategories": [
{
"keyword": "subcat_1_1",
"questiongroups": [
{
"questions": [
{
"keyword": "key_1",
"in_list": true,
"is_name": true
},
{
"keyword": "key_3",
"form_template": "inline_2",
"max_length": 50
}
],
"keyword": "qg_1"
},
{
"questions": [
{
"keyword": "key_2",
"max_length": 50,

12 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

"num_rows": 2
},
{
"keyword": "key_3"
}
],
"keyword": "qg_2"
}
]
},
{
"keyword": "subcat_1_2",
"questiongroups": [
{
"questions": [
{
"keyword": "key_4"
},
{
"keyword": "key_11",
"questiongroup_conditions": [
">0|sample_qg_22"
]
}
],
"keyword": "qg_3"
},
{
"keyword": "qg_22",
"questiongroup_condition": "sample_qg_22",
"questions": [
{
"keyword": "key_27",
"questiongroup_conditions": [
"=='value_27_3'|sample_qg_23"
]
}
]
},
{
"keyword": "qg_23",
"questiongroup_condition": "sample_qg_23",
"questions": [
{
"keyword": "key_28"
}
]
},
{
"keyword": "qg_29",
"detail_level": "sample_plus",
"questions": [
{
"keyword": "key_37"
},
{
"keyword": "key_38"
}

3.2. Questionnaires 13
QCAT Documentation, Release 0.1.0

]
}
]
}
]
},
{
"keyword": "cat_2",
"subcategories": [
{
"keyword": "subcat_2_1",
"questiongroups": [
{
"questions": [
{
"keyword": "key_13",
"questiongroup_conditions": [
"=='value_13_5'|sample_qg_18"
]
}
],
"keyword": "qg_10"
},
{
"keyword": "qg_18",
"questiongroup_condition": "sample_qg_18",
"questions": [
{
"keyword": "key_24"
}
]
}
]
},
{
"keyword": "subcat_2_2a",
"subcategories": [
{
"keyword": "subcat_2_2b",
"questiongroups": [
{
"questions": [
{
"keyword": "key_12",
"view_template": "textinput"
}
],
"keyword": "qg_9"
}
]
}
]
},
{
"keyword": "subcat_2_3a",
"subcategories": [
{
"keyword": "subcat_2_3b",

14 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

"subcategories": [
{
"keyword": "subcat_2_3c",
"questiongroups": [
{
"keyword": "qg_19",
"questions": [
{
"keyword": "key_5",
"in_list": true
}
]
}
]
}
]
}
]
},
{
"keyword": "subcat_2_4",
"subcategories": [
{
"keyword": "subcat_2_4a",
"questiongroups": [
{
"keyword": "qg_20",
"questions": [
{
"keyword": "key_25"
}
]
}
]
},
{
"keyword": "subcat_2_4b",
"subcategories": [
{
"keyword": "subcat_2_4b1",
"subcategories": [
{
"keyword": "subcat_2_4b2",
"questiongroups": [
{
"keyword": "qg_21",
"questions": [
{
"keyword": "key_26"
}
]
}
]
}
]
}
]
}

3.2. Questionnaires 15
QCAT Documentation, Release 0.1.0

]
}
]
},
{
"keyword": "cat_3",
"subcategories": [
{
"keyword": "subcat_3_1",
"questiongroups": [
{
"questions": [
{
"keyword": "key_7"
}
],
"keyword": "qg_5"
},
{
"questions": [
{
"keyword": "key_8"
}
],
"keyword": "qg_6"
},
{
"keyword": "qg_13",
"numbered": "inline",
"questions": [
{
"keyword": "key_17"
},
{
"keyword": "key_18"
}
]
}
]
},
{
"keyword": "subcat_3_2",
"questiongroups": [
{
"keyword": "qg_7",
"numbered": "prefix",
"questions": [
{
"keyword": "key_9"
}
]
},
{
"questions": [
{
"keyword": "key_10"
}
],

16 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

"keyword": "qg_8",
"max_num": 3,
"min_num": 2
}
]
}
]
}
]
},
{
"keyword": "section_2",
"categories": [
{
"keyword": "cat_4",
"subcategories": [
{
"keyword": "subcat_4_1",
"questiongroups": [
{
"questions": [
{
"keyword": "key_14",
"filter_options": {
"order": 1
}
}
],
"keyword": "qg_11"
},
{
"questions": [
{
"keyword": "key_16",
"conditional": true
},
{
"keyword": "key_15",
"conditions": [
"value_15_1|True|key_16"
]
}
],
"keyword": "qg_12"
}
]
},
{
"keyword": "subcat_4_2",
"questiongroups": [
{
"keyword": "qg_16",
"questions": [
{
"keyword": "key_21",
"view_template": "textinput",
"questiongroup_conditions": [
">1|questiongroup_17",

3.2. Questionnaires 17
QCAT Documentation, Release 0.1.0

"<3|questiongroup_17"
]
}
]
},
{
"keyword": "qg_17",
"questiongroup_condition": "questiongroup_17",
"questions": [
{
"keyword": "key_22"
},
{
"keyword": "key_23"
}
]
}
]
},
{
"keyword": "subcat_4_3",
"questiongroups": [
{
"keyword": "qg_24",
"view_template": "bars",
"questions": [
{
"keyword": "key_29"
},
{
"keyword": "key_30"
},
{
"keyword": "key_31"
},
{
"keyword": "key_32"
}
]
}
]
}
]
},
{
"keyword": "cat_5",
"subcategories": [
{
"keyword": "subcat_5_1",
"form_template": "table_1",
"view_template": "table_1",
"table_grouping": [
[
"qg_25",
"qg_27"
],
[
"qg_26",

18 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

"qg_28"
]
],
"questiongroups": [
{
"keyword": "qg_25",
"questions": [
{
"keyword": "key_33"
},
{
"keyword": "key_34"
}
]
},
{
"keyword": "qg_26",
"min_num": 3,
"questions": [
{
"keyword": "key_35"
},
{
"keyword": "key_36"
}
]
},
{
"keyword": "qg_27",
"questions": [
{
"keyword": "key_33"
},
{
"keyword": "key_34"
}
]
},
{
"keyword": "qg_28",
"min_num": 3,
"questions": [
{
"keyword": "key_35"
},
{
"keyword": "key_36"
}
]
}
]
}
]
}
]
}
],
"links": [

3.2. Questionnaires 19
QCAT Documentation, Release 0.1.0

{
"keyword": "samplemulti"
}
]
}

3.2.2 Section Configuration

Contains the configuration of a section.


The configuration of a Section is only part of the Questionnaire Configuration.
See also:
configuration.configuration.QuestionnaireSection

Parent element: Questionnaire Configuration


Child element: Category Configuration

Format

The basic format of the configuration is as follows:

{
# The keyword of the section.
"keyword": "SECTION_KEYWORD",

# (optional)
"view_options": {
# Default: "default"
"template": "TEMPLATE_NAME",

# Default: false
"media_gallery": true
},

# A list of categories.
"categories": [
{
# ...
}
]
}

See also:
For more information on the configuration of its child elements, please refer to their respective documentation:
• Category Configuration
Also refer to the Example of a Questionnaire configuration.

keyword

The keyword of the section.

20 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

view_options

(Optional). An optional object containing configuration options for the view representation of the section.
• template: An optional template name. Must be a valid file name with .html ending in folder templates/
details/section/.
• media_gallery: An optional boolean indicating whether to include a media gallery at the top of the section
or not. The gallery contains all images attached to the questionnaire.

categories

A list of Category Configuration.

3.2.3 Category Configuration

Contains the configuration of a category.


The configuration of a Category is only part of the Questionnaire Configuration.
See also:
configuration.configuration.QuestionnaireCategory

Parent element: Section Configuration


Child element: Subcategory Configuration

Format

The basic format of the configuration is as follows:

{
# The keyword of the category.
"keyword": "CAT_KEYWORD",

# (optional)
"view_options": {
# Default: "default"
"template": "TEMPLATE_NAME",

# Default: false
"use_raw_data": true,

# Default: false
"with_metadata": true,

# Default: {}
"additional_data": {
"QUESTIONGROUP": ["KEY"]
}
},

# A list of subcategories.
"subcategories": [
{

3.2. Questionnaires 21
QCAT Documentation, Release 0.1.0

# ...
}
]
}

See also:
For more information on the configuration of its child elements, please refer to their respective documentation:
• Subcategory Configuration
Also refer to the Example of a Questionnaire configuration.

keyword

The keyword of the category.

view_options

(Optional). An optional object containing configuration options for the view representation of the category.
• template: An optional template name. Must be a valid file name with .html ending in folder templates/
details/category/.
• use_raw_data: An optional boolean indicating whether to add the raw category data to the template or not.
These values can then be used for example for manual rendering of the category details. Defaults to False.
See also:
configuration.configuration.QuestionnaireCategory.get_raw_category_data()
• with_metadata: An optional boolean indicating whether to add the metadata of the current Questionnaire
to the template or not. Defaults to False.
• additional_data: An optional object containing the keywords of questiongroups and questions from which
additional data is to be collected.
Example:

{
"qg_1": ["key_1"]
}

form_options

• helptext_length (int): Overwrite the default length (number of words) of the helptext shown initially
(without the “See more” button).
• numbering (str): An optional numbering of the category.

subcategories

A list of Subcategory Configuration.

22 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

3.2.4 Subcategory Configuration

Contains the configuration of a subcategory.


The configuration of a Subcategory is only part of the Questionnaire Configuration.
See also:
configuration.configuration.QuestionnaireSubcategory

Parent element: Category Configuration


Child element: Questiongroup Configuration

Format

The basic format of the configuration is as follows:

{
# The keyword of the subcategory.
"keyword": "SUBCAT_KEYWORD",

# (optional)
"view_options": {
# Default: "default"
"template": "TEMPLATE_NAME",

# Default: false
"raw_questions": true,

# Default: None
"table_grouping": []
},

# (optional)
"form_options": {
# Default: "default"
"template": "TEMPLATE_NAME",

# Default: ""
"label_tag": "h3",

# Default: ""
"label_class": "top-margin",

# Default: []
"questiongroup_conditions": [],

# Default: ""
"questiongroup_conditions_template": ""
},

# A list of questiongroups.
"questiongroups": [
# ...
],

# A list of subcategories.

3.2. Questionnaires 23
QCAT Documentation, Release 0.1.0

"subcategories": [
# ...
]
}

See also:
For more information on the configuration of its child elements, please refer to their respective documentation:
• Questiongroup Configuration
Also refer to the Example of a Questionnaire configuration.

keyword

The keyword of the category.

view_options

(Optional). An optional object containing configuration options for the view representation of the question.
• template: An optional template name. Must be a valid file name with .html ending in folder templates/
details/subcategory/.
• raw_questions (bool): An optional boolean indicating whether to (additionally) render the questions in
their raw format.
• table_grouping: A nested array to define the layout of the table based on the keywords of the question-
groups of the subcategory.
Example:

"table_grouping": [
["qg_25", "qg_27"],
["qg_26", "qg_28"]
]

Creates the following table (with "view_template": "table_1"):

qg_25 qg_26
qg_26

form_options

(Optional). An optional object containing configuration options for the form representation of the question.
• template: An optional name of a template to be used for the rendering of the subcategory form. The name
of the template needs to match a file with the ending .html inside questionnaire/templates/form/
subcategory/. If not specified, the default layout (default.html) is used.
Please note that some templates require additional options to be set.
• label_tag (str): Specifies the tag used for the label (eg. h3). Used only for template
has_subcategories.

24 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

• label_class (str): Specifies an (additional) class name for the label tag. Currently only used for template
has_subcategories.
• questiongroup_conditions (list): A list of questiongroup conditions to be passed to the subcategory
template in case of special rendering. Must correspond to the list of questiongroup_conditions set in
the form_options of the first key of the first questiongroup.
• questiongroup_conditions_template (str): Indicate a field template to be used for the rendering of
the question which renders the conditional question (eg. checkbox_with_questiongroup). Must be
used in combination with questiongroup_conditions. Template must exist in form/fields/{}.
html.
• helptext_length (int): Overwrite the default length (number of words) of the helptext shown initially
(without the “See more” button).
• numbering (str): An optional numbering of the subcategory.
• has_links (bool): This is only required if a questiongroup within the subcategories is used to link to other
questionnaires. Defaults to false.
See also:
Link Configuration

questiongroups

A list of Questiongroup Configuration.

Important: The options questiongroups and subcategories are exclusive, they should not be set both at
the same time.

subcategories

A list of Subcategory Configuration.

Important: The options questiongroups and subcategories are exclusive, they should not be set both at
the same time.

Form templates

Every subcategory should render a <fieldset> and its label as <legend>. Inside the fieldset, the questiongroups
are to be rendered.
For nested subcategories, use template has_subcategories.
Templates for subcategories are situated in the folder templates/form/subcategory/. They have access to
the following variables:
• formsets (list): A list of tuples containing the configuration and the Django FormFormSet objects of the
questiongroups ([({}, <FormFormSet>)]).
• config (dict): A dictionary containing the configuration of the subcategory. All of the form_options
specified in the configuration are available, as well as the following keys:

3.2. Questionnaires 25
QCAT Documentation, Release 0.1.0

– form_template (str): The name of the template to be rendered next.


– has_changes (bool): A boolean indicating whether there are changes in this subcategory compared the
older version of the questionnaire.
– helptext (str): The helptext for the subcategory.
– label (str): The label of the subcategory.
– next_level (str): Indicates whether the next child to be rendered is another subcategory or a question-
group. Possible values are subcategories or questiongroups.
– numbering (str): The numbering of the subcategory.
– table_grouping (from view_options)
– table_headers (from view_options)
– table_helptexts (from view_options)
– template (str): The name of the current subcategory template.

3.2.5 Questiongroup Configuration

Contains the configuration of a questiongroup.


The configuration of a Questiongroup is stored in a JSON format in the configuration field of
configuration.models.Questiongroup. It can also be overwritten in the Questionnaire Configuration.
See also:
configuration.configuration.QuestionnaireQuestiongroup

Parent element: Subcategory Configuration


Child element: Question Configuration

Format

The basic format of the configuration is as follows:

{
# The keyword of the questiongroup.
"keyword": "QUESTIONGROUP_KEYWORD",

# (optional)
"view_options": {
# Default: "default"
"template": "TEMPLATE_NAME",

# Default: ""
"conditional_question": "KEY_KEYWORD",

# Default: ""
"layout": "before_table"
},

# (optional)
"form_options": {
# Default: "default"

26 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

"template": "TEMPLATE_NAME",

# Default: 1
"min_num": 2,

# Default: 1
"max_num: 3,

# Default: ""
"numbered": "NUMBERED",

# Default: ""
"detail_level": "DETAIL_LEVEL",

# Default: ""
"questiongroup_condition": "CONDITION_NAME",

# Default: "" - can also be a list!


"layout": "before_table",

# Default: ""
"row_class": "no-top-margin".

# Default: "h4"
"label_tag": "h5",

# Default: ""
"label_class": "",

# Default: ""
"table_columns": 2
},

# A list of questions.
"questions": [
# ...
]
}

See also:
For more information on the configuration of its child elements, please refer to their respective documentation:
• Question Configuration
Also refer to the Example of a Questionnaire configuration.

keyword

The keyword of the questiongroup.

Hint: Each keyword of a questiongroup needs to be unique throughout all questionnaires. This is because question-
naire data is stored by their questiongroup keyword and when queried it needs to be mapped to the correct question-
group.

3.2. Questionnaires 27
QCAT Documentation, Release 0.1.0

view_options

(Optional). An optional object containing configuration options for the view representation of the questiongroup.
• template: An optional template name. Must be a valid file name with .html ending in folder templates/
details/questiongroup/.
• conditional_question (str): For conditional questiongroups, the name of the key for which the ques-
tiongroup will be rendered next to. Works for example with subcategory template “image_questiongroups”
• layout (str): Additional indications used for the layout. These depend largely on the template used. Known
values are “before_table” or “label”.
• raw_questions (bool): If set to true, raw questions are added to the template under the variable
raw_questions.
• with_keys (bool): If set to true, a list with all the key labels of the questiongroup is added to the template
(variable keys).

form_options

(Optional). An optional object containing configuration options for the form representation of the question.
• template: An optional template name. Must be a valid file name with .html ending in folder
templates/form/questiongroup/. If not specified, the default layout (default.html)
is used.
• min_num: The minimum for repeating questiongroups to appear. Defaults to 1.
• max_num: The maximum for repeating questiongroups to appear. If larger than min_num, buttons
to add or remove questiongroups will be rendered in the form. Defaults to min_num.
• numbered: An optional parameter if the questiongroup is to be numbered. Currently, mainly the
value display is used.
• detail_level: An optional parameter if the questiongroup contains additional, mostly more de-
tailed questions which are only visible after clicking on a link. This is used for the “Plus”-Questions.
The value of the parameter can be freely chosen.
• questiongroup_condition: An optional name of a condition valid for this questiongroup.
The name must correspond to one of questiongroup_conditions of a Question configura-
tion.
See also:
Question Configuration
• layout (str): General layout indications for the layout of the questiongroup inside the subcategory.
This depends a lot on the subcategory template. Known values are for example “before_table”
used in template “questionnaire/templates/form/subcategory/table_input.html” or “no_label_row”
for tables.
• columns_custom (list): A nested list indicating the distribution of the columns, eg. [[“12”], [“8”,
“4”]]. This is valid for template “columns_custom”.
• user_role (str): A specific configuration used only for template select_user.
• row_class (str): An additional CSS class for the <div class="row"> element containing all
the questions of the questiongroup. Example: “no-top-margin”.
• label_tag (str): Specifies the tag used for the label. Default is h4.

28 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

• label_class (str): Specifies an additional class name for the label tag.
• column_widths (list): Specify the column widths for the table. Used in template table. Ex-
ample:

"column_widths": ["60%", "40%"]

• table_columns (int): Indicate the number of columns of the table. Used by template
table_columns.
• helptext_length (int): Overwrite the default length (number of words) of the helptext shown
initially (without the “See more” button).
• link (str): Required if the questiongroup is a link to other questionnaires. In this case, this value
must contain the name of the configuration which is linked (eg. technologies).

questions

A list of Question Configuration.

Form templates

Templates for questiongroups are situated in the folder templates/form/questiongroup/. They have access
to the following variables:
• formset: A Django FormFormSet object, containing the (repeating) forms (formset.forms) as well as
the management form (formset.management_form) which needs to be rendered in order for the form to
be submitted correctly.
• config (dict): A dictionary containing the configuration of the questiongroup. All of the form_options
specified in the configuration are available, as well as the following keys:
– has_changes (bool): A boolean indicating whether there are changes in this questiongroup compared
the older version of the questionnaire.
– helptext (str): The helptext for the questiongroup.
– keyword (str): The keyword of the questiongroup.
– label (str): The label of the questiongroup (if available).
– options (dict): The options of the keys, ({"key_1": {}}), to be passed to the template of the
question.
– template (str): The name of the current questiongroup template.
– templates (dict): A dictionary of the templates of the questions ({"key_1": {}}), to be passed to
their templates

3.2.6 Question Configuration

Contains the configuration of a question.


The configuration of a Question is only part of the Questionnaire Configuration.
See also:
configuration.configuration.QuestionnaireQuestion

3.2. Questionnaires 29
QCAT Documentation, Release 0.1.0

Parent element: Questiongroup Configuration


Child element: Key Configuration

Format

The basic format of the configuration is as follows:

{
# The keyword of the key of the question.
"keyword": "KEY",

# (optional)
"view_options": {
# Default: "default"
"template": "TEMPLATE_NAME",

# Default: ""
"label_position": "",

# Default: "h5"
"label_tag": "h5",

# Default: ""
"layout": "stacked",

# Default: false
"with_raw_values": true,

# Default: false
"in_list": true,

# Default: false
"is_name": true,
},

# (optional)
"form_options": {
# Default: "default"
"template": "TEMPLATE_NAME",

# Default: None
"max_length": 500,

# Default: 3
"num_rows": 5,

# Default: ""
"helptext_position": "tooltip",

# Default: ""
"label_position": "placeholder",

# Default: false
"conditional": true,

# Default: []

30 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

"questiongroup_conditions": [],
},

# (optional)
"filter_options": {
"order": 1
}
}

See also:
For more information on the configuration of its child elements, please refer to their respective documentation:
• Key Configuration
• Value Configuration
Also refer to the Example of a Questionnaire configuration.

keyword

The keyword of the key of this question.

view_options

(Optional). An optional object containing configuration options for the view representation of the question.
• template: An optional template name. Must be a valid file name with .html ending in folder templates/
details/question/.
• label_position (str): An optional indication for the label placement. Possible values are: none (no label
displayed).
• label_tag (str): Specifies the HTML tag used for the label (eg. h3). By default, the tag <h5> is used.
• layout (str): Additional indications used for the layout of the question. Known values are stacked for
stacked measure bars.
• with_raw_values (bool): Allows to also add the raw values (the keywords) to the list of values. This works
for field types “checkbox”, “cb_bool” and “radio”. Defaults to false.
• in_list: An optional boolean indicating whether this question should appear in the list representation of
questionnaires or not. Defaults to False, meaning that this question is not shown in the list.
• is_name: An optional boolean indicating whether this question represents the name of the entire Question-
naire.

Important: Only one question of the entire Questionnaire can have this flag. If the key is inside a repeating
questiongroup, only the first appearance of the key will be used as name.

• filter: An optional boolean indicating whether this question is filterable or not. If set to True, the question
will appear in the filter dropdown.

3.2. Questionnaires 31
QCAT Documentation, Release 0.1.0

form_options

(Optional). An optional object containing configuration options for the form representation of the question.
• template: An optional template name. Must be a valid file name with .html ending in folder templates/
form/question/.
• max_length: An optional integer to specify the maximum length of characters for this value. Renders as a
validator for text fields. This is only meaningful for key types char (default value: 200) and text (default
value: 500).
• num_rows: An optional integer to define the number of rows to be shown for textarea fields. This is only
meaningful for key type text. The default is 3.
• row_class (str): CSS class name added to the <div class="row single-item"> element containing
both the label and the field.
• label_columns_class (str): CSS class name added to the <div class="columns"> element con-
taining the label.
• field_columns_class (str). CSS class name added to the <div class="columns"> element con-
taining the field.
• helptext_position: An optional name for the placement of helptext related to the question. Possible
values are tooltip (showing the helptext as a tooltip on the question label)
• helptext_length (int): Overwrite the default length (number of words) of the helptext shown initially
(without the “See more” button).
• label_position: An optional name for the display and positioning of the label. Possible values are:
placeholder (showing the label as a placeholder inside the input field)
• has_other (str): A name to be used by questions with key type “radio” to indicate that there is an addi-
tional option “other” with a textfield to specify. The name must be unique and must be the same as used by
other_radio of the other radio key.
• other_radio (str): A name to be used by the char key which acts as “other” radio button. Must be unique
and match the name specified in has_other of the radio key and must be unique.
• field_options (dict): A dictionary containing options which are directly passed as attributes to the input
field. This is currently only used for types int and float and allows for example to directly set the minimum
or maximum values of the field.
Example:

{
"field_options": {
"min": 1900,
"max": "now"
}
}

Please note that “now” is a special keyword and should only used with type int. This will be converted to the
current year.
For float values, there exists an additional field_option named decimals which is an integer specify-
ing the number of decimal places in the output (details).
• question_conditions (list): An optional list of conditions triggering conditional questions within the
same questiongroup. Each condition must have the format "expresssion|condition_name" where
expression is part of a valid (Python and Javascript!) boolean expression and condition_name is the
name of a Question’s question_condition option.

32 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

• question_condition (str): The name of the condition to be triggered (as specified in


question_conditions). Must be unique throughout the configuration.
• questiongroup_conditions: An optional list of conditions triggering conditional questiongroups. Each
condition must have the format "expresssion|condition_name" where expression is part of a
valid (Python and Javascript!) boolean expression and condition_name is the name of a Questiongroup’s
questiongroup_condition option.
Example:

"questiongroup_conditions": [">1|questiongroup_17", "<3|questiongroup_17"]

See also:
Questiongroup Configuration

3.2.7 Key Configuration

The configuration of a Key is stored in a JSON format in the configuration field of configuration.
models.Key.

Hint: The configuration of the key in the database cannot be overwritten in the questionnaire configuration. The
same key can be used multiple times and in several questionnaires so any changes should be done carefully.

Format

The basic format of the configuration is as follows:

{
"type": "TYPE"
}

type

The following options are valid for type. Default type is char.

3.2. Questionnaires 33
QCAT Documentation, Release 0.1.0

char A simple textfield for short text, with the label above the field.
text A textarea for larger text
bool A field for boolean values Yes (stored as True) and No (stored as False). Renders as radio buttons.
measureA field to select measure values (e.g. low, medium, high). Also allows null values. Renders as button
group.
The values of measure fields are stored as integers in the database. This allows easier queries such as
“greater than ‘low’”.
This type requires values related to the key to be present in the database.
A simple checkbox list to allow the selection of multiple values. Renders as checklist.
checkbox
This type requires values related to the key to be present in the database.
A checkbox list with images to allow the selection of multiple values. Renders as checklist with images.
image_checkbox
This type requires values related to the key to be present in the database and to have a valid image_name
configuration.
A select field which allows selection by typing. Renders the field with Chosen.
select_type
select A simple select field without typing.
cb_boolBasically a boolean field but rendered as a single checkbox (selected = true, not selected = false).
date A datepicker field.
file A field to upload any file (as opposed to image
image A field to upload an image.
hidden A hidden input field.
radio A set of radio buttons, needs values.
user_idA special field which allows to select a user.
link_idA special field which allows to select another questionnaire.
int A field rendered as input type=”number”, the validation makes sure it contains only integers.
float A field rendered as input type=”number”, can contain decimal numbers
A select field similar to select_type which lets you select an instance of a model which has to be
select_model
specified in the form_options.
A field rendered as hidden in the form, but displayed like a textfield in the details.
display_only

3.2.8 Value Configuration

The configuration of a Value is stored in a JSON format in the configuration field of configuration.
models.Value.

Hint: The configuration of the value in the database cannot be overwritten in the questionnaire configuration. The
same value can be used in several questionnaires and for multiple keys so any changes should be done carefully.

Format

The basic format of the configuration is as follows:

{
# (optional)
"image_name": ""
}

34 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

image_name

The image_name defines the filename of the image associated with this value. This is in particular required for
values belonging to a key with type image_checklist.

3.2.9 Link Configuration

Links to other questionnaires (eg. from Technologies to Approaches) can be configured within the questiongroup.
However, some options need to be specified at subcategory level.
Example:

{
"keyword": "SUBCAT_KEYWORD",
"form_options": {
"has_links": true
},
"questiongroups": [
{
"keyword": "QUESTIONGROUP_KEYWORD__CONFIGURATION_OF_LINK",
"form_options": {
"template": "select_link",
"link": "CONFIGURATION_OF_LINK",
"max_num": 3
},
"view_options": {
"template": "links"
},
"questions": [
{
"keyword": "link_id"
}
]
}
]
}

Or more concrete:

{
"keyword": "app__1__4",
"form_options": {
"has_links": true
},
"questiongroups": [
{
"keyword": "app_qg__technologies",
"form_options": {
"template": "select_link",
"link": "technologies",
"max_num": 3
},
"view_options": {
"template": "links"
},
"questions": [
{

3.2. Questionnaires 35
QCAT Documentation, Release 0.1.0

"keyword": "link_id"
}
]
}
]
}

Please note that the keyword of the questiongroup is crucial, it needs to contain the name of the configuration
to be linked at the end, separated by __. Examples: app_qg__technologies linking to technologies or
tech_qg__approaches linking to approaches.
For more information, please look at Subcategory Configuration or Questiongroup Configuration

3.3 Settings

3.3.1 Application settings

This chapter covers the configuration of the QCAT application. The pattern `config` from the 12 factor app is
widely followed, so many variables are stored in the environment.
For easy management of environment variables, the package envdir is used. The variables are stored in the folder
`/envs`; your folder should look as follows

envs/
AUTH_API_KEY
AUTH_API_URL
CACHE_URL
DATABASE_URL
DJANGO_ALLOWED_HOSTS
DJANGO_CONFIGURATION
DJANGO_DEBUG
DJANGO_SECRET_KEY
DJANGO_SETTINGS_MODULE
DJANGO_TEMPLATE_DEBUG
DJANGO_USE_CACHING
MAINTENANCE_MODE
TESTING_FIREFOX_PATH

See also:
dj-database-url for the format of `DATABASE_URL`
See also:
django-cache-url for the format of `CACHE_URL`

Django settings

Most of the settings are identical to the Django settings. Please refer to the Django documentation for further infor-
mation.
Following environment variables must be set in order for django to run:
• `DJANGO_CONFIGURATION` (for development: ‘DevDefaultSite’)
• `DJANGO_SETTINGS_MODULE` (for develpment: ‘apps.qcat.settings’)

36 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

• `DATABASE_URL`
• `DJANGO_SECRET_KEY`

QCAT settings

API_PAGE_SIZE

Page size of results for the API providing questionnaire details.

AUTH_API_KEY

AUTH_API_TOKEN

The API token used for the authentication.


Default: None

AUTH_API_URL

AUTH_API_USER

AUTH_COOKIE_NAME

AUTH_LOGIN_FORM

DEPLOY_TIMEOUT

Timeout between announcement of deploy and actual maintenance window in seconds.

ES_ANALYZERS

ES_HOST

ES_INDEX_PREFIX

ES_NESTED_FIELDS_LIMIT

ES_PORT

ES_QUERY_RESERVED_CHARS

Some charactes have special meaning to ES queries. https://www.elastic.co/guide/en/elasticsearch/reference/2.0/


query-dsl-query-string-query.html#_reserved_characters

3.3. Settings 37
QCAT Documentation, Release 0.1.0

GOOGLE_MAPS_JAVASCRIPT_API_KEY

GOOGLE_WEBMASTER_TOOLS_KEY

GRAPPELLI_ADMIN_TITLE

GRAPPELLI_INDEX_DASHBOARD

HOST_STRING_DEMO

Used for continuous delivery (fabric).

HOST_STRING_DEV

Used for continuous delivery (fabric).

HOST_STRING_LIVE

Used for continuous delivery (fabric).

IS_ACTIVE_FEATURE_MODULE

Feature toggle for questionnaire-modules

IS_ACTIVE_FEATURE_SUMMARY

Feature toggle for summaries

IS_ACTIVE_FEATURE_WATERSHED

Feature toggle for questionnaire ‘watershed’

KEY_PREFIX

LOCALE_PATHS

LOGIN_URL

MAINTENANCE_LOCKFILE_PATH

MAINTENANCE_MODE

See https://github.com/shanx/django-maintenancemode

38 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

NEXT_MAINTENANCE

See https://github.com/shanx/django-maintenancemode

NOSE_ARGS

PIWIK_API_VERSION

PIWIK_AUTH_TOKEN

PIWIK_SITE_ID

PIWIK_URL

REACTIVATE_WOCAT_ACCOUNT_URL

An URL to which users are redirected if the login failed because their account is not yet activated. Background is that
upon switching to the new WOCAT website in 2017, all existing user accounts have to be reactivated manually.
Default: https://beta.wocat.net/accounts/reactivate/

REST_FRAMEWORK

Settings for: http://www.django-rest-framework.org/

SEND_MAILS

SENTRY_DSN

See https://docs.sentry.io/clients/python/integrations/django/

SUMMARY_PDF_PATH

Path to folder to store/’cache’ created pdfs

SWAGGER_SETTINGS

See https://django-rest-swagger.readthedocs.io/en/latest/

3.3. Settings 39
QCAT Documentation, Release 0.1.0

TEMP_UNCCD_TEST

TESTING_FIREFOX_PATH

THUMBNAIL_ALIASES

TOUCH_FILE_DEMO

Location of uwsgi-touchfile, used for continuous delivery.

TOUCH_FILE_DEV

Location of uwsgi-touchfile, used for continuous delivery.

TOUCH_FILE_LIVE

Location of uwsgi-touchfile, used for continuous delivery.

UPLOAD_IMAGE_THUMBNAIL_FORMATS

A dictionary specifying the different thumbnail formats for images. For every uploaded image, a thumbnail is created
in each of the formats.
Example:

UPLOAD_IMAGE_THUMBNAIL_FORMATS = {

# '[NAME]': ([WIDTH], [HEIGHT])


'header': (900, 300),

'small': (200, 100),


}

UPLOAD_MAX_FILE_SIZE

An integer indicating the maximum file size for a single file upload. In Bytes.

UPLOAD_VALID_FILES

A dictionary indicating what file types are valid for upload and with which extension they shall be saved.
Example:

UPLOAD_VALID_FILES = {

# 'TYPE': Used to group different types of files


'image': (

# ('[CONTENT_TYPE]', 'FILE_EXTENSION')

40 Chapter 3. Configuration
QCAT Documentation, Release 0.1.0

('image/jpeg', 'jpg'),
('image/png', 'png'),
('image/gif', 'gif'),
),
'document': (
('application/pdf', 'pdf'),
)
}

USE_NEW_WOCAT_AUTHENTICATION

A boolean indicating whether to use the new (2017) WOCAT website as authentication service or not.
Default: False

WARN_HEADER

Text to display as warn header at the bottom of the page.

WOCAT_IMPORT_DATABASE_URL

WORD_WRAP_LANGUAGES

List of languages to add the css-attribute: word-wrap. Use this with languages without spaces between words, such as
Khmer.

3.3. Settings 41
QCAT Documentation, Release 0.1.0

42 Chapter 3. Configuration
CHAPTER 4

Development

4.1 Installation

This section covers the installation of QCAT for local development. For instructions on how to deploy QCAT to a
server, refer to the Deployment section.

4.1.1 Prerequisites

The following prerequisites are needed. Make sure to have them installed on your system.

Python 3

QCAT is written in Python 3, which is already installed on many operating systems.

Git

The source code of QCAT is managed in Git, a free and open source distributed version control system.

PostgreSQL

PostgreSQL is the database management system behind QCAT. In order to install QCAT, you need to create a database
first and install the PostGIS extension for this database.

Important: At least version 9.4 of PostgreSQL is needed as support of the JSON-B data type is required.

43
QCAT Documentation, Release 0.1.0

Elasticsearch

Elasticsearch is used as a search engine to query the questionnaires. This project is developed with version 2.3.0 of
elasticsearch.
See also:
Elasticsearch

4.1.2 Installation on a UNIX system

These instructions will take you through the process of installing QCAT on your computer, assuming that you are
running a UNIX system (for example Ubuntu). The package virtualenvwrapper is highly recommended.

Preparation

Create a folder for the project and create a virtual environment in it:

$ mkproject qcat

Get the code:

$ git clone https://github.com/CDE-UNIBE/qcat.git .

The custom packages for this application are in the folder `apps`. This directory must be added to your virtualenv:

$ add2virtualenv apps/

This command must be executed in the root directory of your activated virtual environment.

Installation: Application

Switch to the source folder, activate the virtual environment and install the dependencies for the development environ-
ment:

$ cd qcat
$ source ../env/bin/activate
(env)$ pip3 install -r requirements/development.txt

Hint: If the installation of the requirements produces errors concerning psycopg2, make sure you have the
python3-dev package installed:

sudo apt-get install python3-dev

Create and set up a database (with PostGIS extension).


Make sure that all required environment variables are set as described in Application settings

Hint: Authentication happens against the WOCAT user database, an API key is needed for this.

Let Django create the database tables for you:

44 Chapter 4. Development
QCAT Documentation, Release 0.1.0

(env)$ python3 manage.py migrate

Load the initial data of QCAT:

(env)$ python3 manage.py load_qcat_data

Installation: Static files

The static files (such as CSS or JavaScript files and libraries) are managed using Bower and GruntJS, both requiring
the NodeJS platform.
Install NodeJS and its package manager:

sudo apt-get install nodejs nodejs-legacy npm

Use NPM to install Bower and Grunt:

sudo npm install -g grunt-cli bower

Install the project dependencies:

sudo npm install

Let Bower collect the required libraries:

bower install

Use Grunt to build the static files:

grunt build

Hint: See the documentation on Grunt for additional grunt commands.

Run

Run the application:

(env)$ python3 manage.py runserver

Open your browser and go to http://localhost:8000 to see if everything worked.

Important: You need to set up Elasticsearch for QCAT to work properly. If you are logged in as an administrator,
there is an entry in the user menu allowing you to create and update the Elasticsearch indices.
See also:
Elasticsearch

4.1. Installation 45
QCAT Documentation, Release 0.1.0

4.2 Data Model

4.3 Data Format

4.3.1 Questionnaire Storage

The data of questionnaires is stored in a JSON format in the data field of the questionnaire.models.
Questionnaire model.

Questiongroups

• The data is stored grouped by questiongroups. Questiongroups are formed based on thematic coherence of
similar questions or if questions can be repeated multiple times.
• The keyword of configuration.models.Questiongroup (e.g. qg_1, qg_2, . . . ) is required as an
identifier of the questiongroup. This way it is not necessary to identify questiongroups based on their questions.
The basic format of the data is as follows:

{
"qg_1": [
{
# Keys and values of qg_1
},
{
# Repeated keys and values of qg_1
},
# ...
],
"qg_2": [
# (Repeated) Keys and values of qg_2
],
# Further questiongroup data

46 Chapter 4. Development
QCAT Documentation, Release 0.1.0

# ...
}

Keys and Values

Keys and values are in general stored as "key": "value" pair inside the questiongroup dictionary. However,
some of the values are stored a bit differently, based on the type of the value.
• Predefined values: Predefined values (e.g. from dropdowns) are stored only as the keyword of the
configuration.models.Value:

{
"key": "value_1"
}

The translation of the value can then be looked up through the relation of the value to configuration.
models.Translation.
• Multiple predefined values: Multiple predefined values (e.g. from checkboxes) are stored as an array of
keywords of the configuration.models.Value:

{
"key": [
"value_1",
"value_2"
]
}

The translation of the values can then be looked up through the relation of the values to configuration.
models.Translation.
• Freetext: Freetext values (e.g. from textfields) can be translated and are stored as dictionary with the locale in
which they were entered as key:

{
"key": {
"en": "Value 1",
"es": "Valor 1"
}
}

This allows multiple translations for freetext. Each questionnaire has a many-to-many relation (
questionnaire.models.QuestionnaireTranslation) to languages. This allows easy access to
the languages in which a questionnaire is available (without having to look inside the data JSON). This relation
has an additional field to flag the original language in which the questionnaire was filled out first.

Example

A concrete example of how the questionnaires are stored:

{
# Specification of SLM Technology (Part 1)
"tech_specification_1": [
{
# 2.1 Definition of Technology (in one sentence)

4.3. Data Format 47


QCAT Documentation, Release 0.1.0

"tech_definition": {
"en": "Continuous breeding of earthworms in boxes for production of high
˓→quality organic compost.",

"es": "Hacer una crianza permanente de lombrices para producir abono orgánico
˓→de alta calidad."

},
# 2.2 Description of the SLM Technology
"tech_description": {
"en": "Vermiculture is a simple and cheap way to produce a continuous supply
˓→of organic compost of high quality. Eisenia foetida, the Red Californian earthworm

˓→(also called ‘the red wiggler’) is ideal for vermiculture since it is adapted to a

˓→wide range of environmental conditions. Under culture, the worms are kept under

˓→shade, in long wooden boxes filled with earth, cattle manure and an absorbent

˓→material (eg straw). The box is covered by sheet metal (or wood, thick plastic

˓→sheeting, or banana leaves) to protect the worms against UV radiation and birds/

˓→chickens, and also to maintain a favourably humid microclimate. Fresh cattle manure

˓→is a perfect food for the worms, but rotten coffee pulp can also be fed. Chopped

˓→crop residues (eg cowpeas, leucaena leaves or other legumes) may be added.",

"es": "Se construye una canoa de madera en un lugar con sombra (ej. debajo de
˓→árboles). La canoa se tapa con zinc, madera o otros materiales para protejer las

˓→lombrices contra sus enemigos y para conservar la humedad. Un alimento adecuado

˓→para las lombrices es el estiércol fresco de vaca, también se les puede echar

˓→material vegetal verde (Terciopelo, Gandúl, Leucaena, etc.), preferiblemente picada

˓→o semidescompuesta ya que las lombrices no tienen dientes más bien chupan

˓→partículas de materia orgánica en el suelo. El abono se aplica como fertilizante a

˓→cultivos, ha demostrado ser muy eficiente en sus efectos al aumentar la producción

˓→de los cultivos. Es importante darle un mantenimiento continua a la lombricultura

˓→(mantener humedad, dar alimento cada tres dias), de esta manera se produce abono

˓→constantemente con cantidades cada vez más crecientes ya que las lombrices se

˓→reproducen rápidamente en un ambiente adecuado. Se utiliza en la mayoría de los

˓→casos la Lombriz Roja de California, la cual es un híbrido de varias especies,

˓→criado en los años 50 en California para tener una lombriz prolífica, fácil a criar

˓→en cautiverio y adaptado a diferentes medios. También se puede utilizar la Cubana

˓→roja. Las lombrices son unos de los organismos principales en la cadena de la

˓→descomposición de la materia orgánica y en la formación de humus estable en el

˓→suelo."

}
}
],
# Specification of SLM Technology (Part 2)
"tech_specification_2": [
{
# 2.4 Land use
"cropland": 5, # High
"forest_woodlands": 1, # Low
"cropland_sub": [
"cropland_annual_cropping",
"cropland_rainfed"
]
}
]
}

Todo: This does not really belong here

Service output:

48 Chapter 4. Development
QCAT Documentation, Release 0.1.0

• With hierarchy (categories and subcategories)

4.4 Elasticsearch

Elasticsearch is used as a search engine to query the questionnaires.

Important: The indices in Elasticsearch only contain public Questionnaires ( with status = active). If pending
questionnaires (eg. the pending changes of the current user) are to be displayed, use a database query instead of
Elasticsearch.

4.4.1 Administration

There is an administration panel available for superusers. It allows to create and update indices. The panel can be
accessed in the user menu or directly via /search/admin/.

4.4.2 Structure

The different indices in QCAT are structured as follows:


/[index]/[type]/[id]
• index: [prefix][questionnaire_type] (examples: qcat_technologies,
qcat_approaches).
– The prefix can be set in the settings.
– The index is actually an alias pointing to an index in behind (for example qcat_technologies_1).
This allows to update the mapping of an index without any downtime (see also https://www.elastic.co/
blog/changing-mapping-with-zero-downtime).
• type: questionnaire. This is currently always set to questionnaire.
• id: identifier. The identifier of the questionnaire.

4.4.3 Document format

A document in elasticsearch contains the following entries (in _source):

{
"data": {
# A copy of the data dictionary as stored in the JSONB-Field of
# questionnaire in the database.
},
"list_data": {
# A dictionary containing the entries used for the list
# representation (as specified in the questionnaire configuration)
},
"created": "[timestamp]",
"updated": "[timestamp]",
"code": "[code of the questionnaire]",
"name": {
# A dictionary containing the translations of the name field (as

4.4. Elasticsearch 49
QCAT Documentation, Release 0.1.0

# specified in the questionnaire configuration)


},
"configurations": [
# A list of the configurations in which this questionnaire is
# available
],
"translations": [
# A list of the translations in which this questionnaire is
# available
]
}

4.4.4 Example

Example of a document stored in Elasticsearch:

{
"_index": "qcat_test_technologies_1",
"_type": "questionnaire",
"_id": "101",
"_score": 1,
"_source": {
"translations": [
"fr",
"en"
],
"data": {
"tech_qg_2": [
{
"tech_definition": {
"fr": "Ceci est la déscription 1 en français.",
"en": "This is the definition of the first WOCAT practice."
}
}
],
"qg_name": [
{
"name": {
"fr": "WOCAT 1 en français",
"en": "WOCAT practice 1"
}
}
]
},
"list_data": {
"name": {
"fr": "WOCAT 1 en français",
"en": "WOCAT practice 1"
},
"tech_definition": {
"fr": "Ceci est la déscription 1 en français.",
"en": "This is the definition of the first WOCAT practice."
}
},
"code": "tech_1",
"updated": "2015-02-10T16:07:20.847000+00:00",

50 Chapter 4. Development
QCAT Documentation, Release 0.1.0

"name": {
"en": "Unknown name"
},
"created": "2015-02-10T16:07:20.847000+00:00",
"configurations": [
"technologies"
]
}
}

4.4.5 Helper functions

The helper functions for Elasticsearch are inside the Django app search.
• search.search.advanced_search(): The main function used to query questionnaires based on their
configurations, codes, name and other attributes.

4.5 Data flow

• All data is saved in the Postgres database.


• Public questionnaires are put into the elasticsearch index.
• Converting a model instance into JSON (for elasticsearch) is handled by the serializer: questionnaire.
serializers.QuestionnaireSerializer
• All relevant data (see below) must be available for objects from the model and elasticsearch; serializing and
deserializing must work in both ways.

4.5.1 Website

• The list view on qcat.wocat.net accesses eleasticsearch only.


• The detail view on qcat.wocat.net calls the method get_details on the configuration of the serialized ques-
tionnaire.

4.5.2 API

• The list view lists all data from elasticsearch.


• The detail view on qcat.wocat.net calls the method get_details on the configuration of the serialized ques-
tionnaire.

4.5.3 Serializing

• If possible, the serializer calls model properties.


• All data which is depending on the config calls a method on the serializer
• The configuration is loaded when the serializer is instantiated.

4.5. Data flow 51


QCAT Documentation, Release 0.1.0

4.6 User Groups

The following user groups exist:

• Administrators
• Translators

4.6.1 Administrators

Access to admin page Yes

Administrators are basically superusers, having every permission there is.

4.6.2 Translators

Access to admin page No

4.7 Testing

4.7.1 Tests

QCAT is tested using functional tests covering the interaction on the web site and unit tests which test isolated pieces
of the code.

Important: The functional tests are based on Firefox. The Selenium WebDriver and its Python bindings used to run
the tests do not suppor the latest (default) version of Firefox.
Therefore, the functional tests are skipped by default. In order to run them, you need to first download an older version
of Firefox (e.g. version 28). Then you need to specify the path to this version of Firefox in your settings_local.
py file, e.g.:

TESTING_FIREFOX_PATH = '/path/to/old/version/of/firefox'

Run all tests:

(env)$ python3 manage.py test

Run only selected based on app:

(env)$ python3 manage.py test accounts

Run only selected tests based on file path:

(env)$ python3 manage.py test functional_tests.test_login

52 Chapter 4. Development
QCAT Documentation, Release 0.1.0

Run only selected tests based on attribute:

(env)$ python3 manage.py test --attr=unit

(env)$ python3 manage.py test --attr='!functional'

The following attributes are available: unit, functional.


To disable the output of logging information, use the flag --nologcapture:

(env)$ python3 manage.py test --nologcapture

4.7.2 Coverage

You can measure the code coverage of your tests through Coverage.
Run the tests with coverage:

(env)$ python3 manage.py test --with-coverage

This will create a report which can be found under coverage_html/index.html.

4.7.3 Stress tests

To check the performance of all parts, some stress tests are included. Docker is required to run them, the tests are
written with locustio. As locustio doesn’t work with python3, a dockerimage is provided. To execute the tests,
proceed as follows (from the project root) and then open the browser:

(env)$ cd stress_tests && ./test.sh && cd -

Don’t forget to stop and remove all docker containers after the tests:

$ docker stop $(docker ps -a -q) && docker rm $(docker ps -a -q)

To (force) remove all images, run:

$ docker rmi -f $(docker images -q)

To only create the dockerimage and run it, execute following commands:

(env)$ cd stress_tests
(env)$ docker build -t locust .
(env)$ docker run --rm -P locust

This starts a docker container with locust (on python 2.7). The IP address of the docker container is listed with:

$ docker network inspect bridge

With the IP for the running container, open the the URL <container ID>:8089. When actively developing the locustfile,
the stress_tests folder can be linked into the docker image:

(env)$ docker run -v <path_to_qcat>/stress_tests:/locust -P locust --host=<your_host>

4.7. Testing 53
QCAT Documentation, Release 0.1.0

4.8 Translations

The source language of this project is English. Refer to the django docs for translations within django.
All fixtures for configurations and questionnaires are expected in English. Additional languages in the fixtures will
not be used.

4.8.1 Basics

• Translations are handled separately for the texts from django (i18n in python files) and questionnaires (i18n in
models; see questionnaire.models.Translation).
• Historically, a jsonb field stores all translations. The structure is: {'configuration_type':
{'keyword': {'en': 'string ahoy'}}}
• This is caused by the way configurations are created: as fixtures.
• Translation changes are expected to happen often, occasionally new languages will be introduced. Managing
translations should require minimal effort from developers.
• These preconditions and the requirement for one system to handle all translations result in a workaround.
• gettext is the ‘default’ way to handle translations.

4.8.2 Workflow

• A string freeze is announced for before deploying to production.


• Creation of new .po files is therefore only allowed on the develop branch
• The command makemessages handles the following:
– Get latest resources from Transifex
– If the -fp flag is set, the pull is ‘forced’. This means that local translation files are overwritten. By default,
local files are not overwritten if they are newer than the version on Transifex.
– If new files are pulled, the po files are compiled (to mo files)
– Check, if new translations for configurations are available. If so, the content is written into a separate
model. A temporary file based on this model is created, this temporary file is then parsed by djangos own
makemessages command.
– Djangos makemessages creates .po files
– The user is asked if the new files should be uploaded to Transifex.

4.8.3 Todo

• Check if txgh would be helpful.


• The current workflow is rather strict (no translations on feature branches, workaround with temporary file).
Reviewing this workflow is recommended.

54 Chapter 4. Development
QCAT Documentation, Release 0.1.0

4.9 Deployment

While it is perfectly fine to deploy QCAT manually, it comes with a script which allows automatic deployment. This
is especially helpful for developers to update the server with a single command.
The following section covers the automatic deployment with a Python library called Fabric.

4.9.1 Install Fabric

Fabric is not part of the requirements of the application and needs to be installed separately. At the time of writing,
Fabric is not yet ported to Python 3.

(env)$ pip2 install fabric

If pip2 is not available, install fabric outside of the virtual environment.

4.9.2 Process

• Changes are always commited to feature branches.


• The git-flow model is in use.
• Only Selected people from the CDE (Centre for Development and Environment) can merge commits into the
branches develop and master.
• Shippable is monitoring these branches, new commits trigger a deployment.
• The configuration for shippable is stored in the file: shippable.yml
– The host string is a secure value, which be generated on the platform.
– Before the actual deployment is started, all tests are run.
– If no tests fail, the deployment is started.
• Deployment is handled with Fabric.
• For the git branches develop and master, respective environments are created.
• Manual deployment should be avoided.

4.9.3 Provision

Warning: The following steps need to be done only once for each server but nothing should break if
you run the command several repeatedly.

In order to prepare the server for deployment, you need to create a user with the appropriate rights on the host server
and create a folder for the app to live in. The script assumes the application will live in /srv/webapps/qcat/.
Then run the following command:

(env)$ fab provision -H [user]@[server]

4.9. Deployment 55
QCAT Documentation, Release 0.1.0

This will install the required software, create the folder structures for the app and get the latest source of the app from
its repository.
You will then have to create the environment variables and set the database connection and adapt other settings:
Application settings

4.9.4 Deploy

To deploy the latest code to the server, use the following command:

(env)$ fab <environment> deploy -H [user]@[server]

If needed, add and enable the site in Apache.

4.9.5 Update recipes

Update server and reset database

1. Delete the database tables.


2. Run the update script:

[local] (env)$ fab deploy -H user@server

3. In Search Index Administration panel, delete all caches.


4. On the server, load the fixtures:

[server] (env)$ python3 manage.py loaddata wocat.json

5. In Search Index Aministration panel: delete and recreate indices.


6. Eventually load data from Search Index Administration panel.

Update server

1. Run the update script:

[local] (env)$ fab deploy -H user@server

2. In Search Index Administration panel, delete all caches.


3. On the server, load the fixtures:

[server] (env)$ python3 manage.py loaddata wocat.json

4. In Search Index Aministration panel: delete, recreate and update indices.

4.10 Django Snippets

A collection of useful Django snippets.

56 Chapter 4. Development
QCAT Documentation, Release 0.1.0

4.10.1 Database migration

To detect the latest changes made to the data model and create a script reflecting these changes, use:

(env)$ python3 manage.py makemigrations

To apply the created migration script to a database, run:

(env)$ python3 manage.py migrate

4.10.2 Fixtures

Create fixture from database

Usage:

(env)$ python3 manage.py dumpdata [appname] --indent 4 > [file]

Example:

(env)$ python3 manage.py dumpdata configuration --indent 4 > sample.json

Use the flag -n if you don’t want to include primary keys in the fixture:

(env)$ python3 manage.py dumpdata -n --indent 4 auth.Group > accounts/fixtures/


˓→initial_data.json

Load data from fixture

Usage:

(env)$ python3 manage.py loaddata [file]

Example:

(env)$ python3 manage.py loaddata sample.json

4.10.3 Graph Data Model

You can let Django (through django-extensions) create graphs of your data model automatically:

(env)$ python3 manage.py graph_models -a -g -o docs/images/qcat_datamodel.png

4.11 Grunt

GruntJS is a task runner which is used to compile and provide static files of QCAT. More information on Grunt can be
found on their homepage.

4.11. Grunt 57
QCAT Documentation, Release 0.1.0

4.11.1 Commands

The following grunt commands are available:

Command Action
grunt Build (uncompressed) and run the server
grunt build Build (uncompressed)
grunt build:deploy Build (compressed)
grunt server Run the server

58 Chapter 4. Development
CHAPTER 5

Contributions

5.1 Translations

Thanks for wanting us to help us translate the SLM database! This article covers instructions to get you started.

5.1.1 Transifex

The translation of the strings on the Website is done with Transifex where you need a free account. We will then add
you as translators to QCAT on Transifex.
If you do not have an account for Transifex yet, you can send us your e-mail address and we will add you as a translator
to QCAT on Transifex. You will receive an e-mail with instructions to set up your Transifex account.
If you already have an account for Transifex, you can send us your username or the e-mail address of your account
and we will add you as a translator to QCAT on Transifex.

5.1.2 Translating on Transifex

Transifex has a very good documentation of the translation process on their website. Particularly helpful are the pages
on Getting Started as a Translator and Translating with the Web Editor.
Please refer to their general documentation for further help.

5.1.3 Hints

No instant updates of translations

The translations on the QCAT website are not updated instantly. The developers need to trigger an update for the new
translations to appear on the site. Therefore if you have finished your translations, let the developers know that they
should update the website.

59
QCAT Documentation, Release 0.1.0

HTML tags in translations

Sometimes, there are HTML tags (such as <strong></strong> in the translation. These tags need to be added
exactly as they are in the translation as well. Make sure to close the tags: after each <strong>, there should be a
</strong>. If you are not sure whether you have closed all tags, there is a service to check for closing HTML tags.
It can occur that there are strings inside the HTML tags (such as <div class="row">Content</div>). These
strings inside the HTML tag (in this case row) should not be translated.
Examples:

Text Translation text


<strong>Type of measure</strong>: refer to 3.6 <strong>Type de mesures</strong>: se référez à la sec-
tion 3.6
<div class=”row”>Refer to 3.6</div> <div class=”row”>Se référez à la section 3.6</div>
<div class=”row”><div <div class=”row”><div
class=”medium-6 columns”><img class=”medium-6 columns”><img
src=”/static/assets/img/smallmedium_QTKEN05_1.jpg”></div></div>
src=”/static/assets/img/smallmedium_QTKEN05_1.jpg”></div></div>

Placeholders in translations

Curly brackets ({}) serve as placeholders and should be added exactly as they are in the translation as well. Sometimes,
they contain keywords (such as {user}) which should not be translated but added identically to the translation.
Other placeholders are %(keyword)s. Again, these need to be added exactly as they are in the translation.

Hint: In Transifex, these placeholders are highlighted in the original text in an orange color. You can click on these
highlighted placeholders in the original text to copy them to the translation.

Text Translation text


Welcome {} Bienvenue {}
This questionnaire is locked for editing by {user}. Ce questionnaire est verrouillé pour modification par {user}.
View this %(questionnaire_type)s. Voir cette %(questionnaire_type)s.

QCAT is currently under heavy development. If you are interested in the progress of the development, have a look
at the issues on the Redmine page of the project. Or see the List of ToDo’s for open issues. Opbeat provides great
services for application monitoring and error reporting.

60 Chapter 5. Contributions
CHAPTER 6

API

6.1 API Documentation

QCAT provides an API to query the contents of the Questionnaires.


The current version of the API is: v2.

6.1.1 QCAT API v2

Welcome to the documentation of version 2 of the QCAT API.


Additional information on the API can be found on the interactive documentation page allowing to try out available
requests.
The example requests below are either for the command line tool curl or for the GUI application Postman.

• Authorization
– Example request with curl
– Example request with Postman
• List of questionnaires
– Example request with curl
– Example request with Postman
– Code examples
• Details of questionnaire
– Example request with curl
– Example request with Postman

61
QCAT Documentation, Release 0.1.0

Authorization

Requests to the QCAT API require an authorization token in the header of the request. The token can be obtained with
this endpoint, a WOCAT user account is required to obtain a token. Please specify what you will use the token for as
“notes”.
Endpoint: /api/v2/auth-token/
Allowed method: POST
Post data: username: The username of your WOCAT account
password: The password of your WOCAT account
notes: A short note indicating the purpose of the token

Example request with curl

Request:

curl -X POST -d '{"username": "WOCAT_USERNAME", "password": "WOCAT_PASSWORD", "notes


˓→": "This token will be used for testing"}' -H "Content-Type: application/json"

˓→https://qcat.wocat.net/en/api/v2/auth-token/

Response:

{"token":"0e03f8061c83e58d1595c3b21ddce9712233cb4e"}

62 Chapter 6. API
QCAT Documentation, Release 0.1.0

Example request with Postman

List of questionnaires

Return a list of Questionnaires. The same filter parameters as for the list view (search or filter) in QCAT can be passed.
Endpoint: /api/v2/questionnaires/
Allowed method: GET
Request headers: Authorization: Your authorization token for the QCAT API. Specified in the format Token
AUTH_TOKEN
Accept: Optionally specify the format of the response. Available formats are JSON (application/json),
XML (application/xml) and CSV (text/csv). Default: application/json
Optional Get parameters: Basically, the same parameters as for the list view in QCAT can be provided, namely page,
type and all the filter parameters used for the list view.

Example request with curl

Request:

6.1. API Documentation 63


QCAT Documentation, Release 0.1.0

curl -X GET -H 'Authorization: Token 0e03f8061c83e58d1595c3b21ddce9712233cb4e' -H


˓→'Accept: application/json' https://qcat.wocat.net/en/api/v2/questionnaires/

Response:

{
"count": 1297,
"next": "https://qcat.wocat.net/en/api/v2/questionnaires/?page=2",
"previous": "",
"results": [
{
"name": "Participatory action research on drip irrigation",
"updated": "2017-06-28T14:43:10.622384Z",
"code": "approaches_2350",
"url": "/en/wocat/approaches/view/approaches_2350/",
"details": "/en/api/v2/questionnaires/approaches_2350/"
},
{
"name": "Farmer field schools on integrated plant nutrient systems",
"updated": "2017-06-28T14:33:18.215042Z",
"code": "approaches_2351",
"url": "/en/wocat/approaches/view/approaches_2351/",
"details": "/en/api/v2/questionnaires/approaches_2351/"
},
// ...
]
}

64 Chapter 6. API
QCAT Documentation, Release 0.1.0

Example request with Postman

Code examples

• Example code to collect all Questionnaires (in Python, using the Requests library)

Details of questionnaire

Return a single Questionnaire by its code. The returned data contains the full configuration (including labels of
sections, questiongroups etc.).
Endpoint: /api/v2/questionnaires/{identifier}/
Allowed method: GET
Request headers: Authorization: Your authorization token for the QCAT API. Specified in the format Token
AUTH_TOKEN
Accept: Optionally specify the format of the response. Available formats are JSON (application/json),
XML (application/xml) and CSV (text/csv). Default: application/json

6.1. API Documentation 65


QCAT Documentation, Release 0.1.0

Example request with curl

Request:

curl -X GET -H 'Authorization: Token 0e03f8061c83e58d1595c3b21ddce9712233cb4e' -H


˓→'Accept: application/json' https://qcat.wocat.net/en/api/v2/questionnaires/

˓→approaches_2350/

Response:

{
"section_general_information": {
"label": "General Information",
"children": {
"app__1": {
"label": "General information",
"children": {
"app__0__1": {
"label": "Image",
"children": {
"qg_image": {
"label": "",
"children": {
"image": {
"label": "Image",
"value": [
{
"in_list": true,
"additional_translations": {},
"content_type": "image/jpeg",
"preview_image": "/upload/7f/0/7f06837f-0d6e-428a-999f-
˓→98d3a2f7a115.jpg",

"key": "Image",
"value": "/upload/ef/e/efe3d278-6620-49ed-b491-0ce29db214bd.
˓→jpg",

"template": "raw"
}
]
},
"image_caption": {
"label": "Caption, explanation of photo",
"value": [
{
"additional_translations": {},
"key": "Caption, explanation of photo",
"value": "On-farm demonstration and exchange visits: women
˓→demonstrating the system to visitors",

"template": "raw"
}
]
}
}
}
}
},
// ...
}
}

66 Chapter 6. API
QCAT Documentation, Release 0.1.0

}
},
// ...
}

Example request with Postman

6.1.2 QCAT API v1

Version 1 is not the current version of the QCAT API anymore. Currently, there is no documentation of version 1
available.
Please use the current version of the API and refer to its documentation.

6.1. API Documentation 67


QCAT Documentation, Release 0.1.0

68 Chapter 6. API
CHAPTER 7

Hosting

7.1 Hosting

This chapter describes the setup on the servers that host this project. This project can be run on any kind of setup that
supports wsgi, the following information describes one possible implementation. All configuration files are stored in
the folder serverconfig.

7.1.1 Architecture

Apache is used as reverse proxy; uwsgi serves the application itself.

Apache

The configuration from serverconfig/apache_<environment>.conf may directly be used as symlink in


your allowed hosts. This configuration is built on Apache version 2.4.7 and ensures that:
• All traffic is redirected to use HTTPS
• The communication with the application server is handled with a socket file
Following Apache modules must be enabled:
• a2enmod proxy
• a2enmod rewrite
• a2enmod deflate
• a2enmod headers
The Apache server may be replaced with nginx, if traffic increases heavily.

69
QCAT Documentation, Release 0.1.0

Uwsgi

This is the actual application server (see uwsgi docs). It should be run in the emperor/tyrant mode. This configuration
is built for uwsgi version 2.0.12.
A sample configuration for this application:
• Emperor: adapt the script: serverconfig/uwsgi_emperor.conf and create a new file in /etc/init.
• Vassals: Symlink (serverconfig/uwsgi_<environment>.conf) in the folder that is ruled by your
emperor.

7.2 Latest changes

7.3 Code

7.3.1 Source

The code of QCAT can be found on Github.

7.3.2 Modules

accounts

The Django app accounts handles the authentication and authorization of users.

accounts.authentication

accounts.forms

accounts.models

accounts.urls

accounts.views

configuration

The Django app configuration handles the configuration of the Questionnaires.

70 Chapter 7. Hosting
QCAT Documentation, Release 0.1.0

configuration.configuration

configuration.models

configuration.views

Notifications

The Django app notifications handles the creation and display of logs for the review process. These are the
most important decisions

Signals

• Signals are used to fire events that mark a change in the workflow
• Classic functions could be used, the decision for signals was made because
– More receivers are likely to be implemented soon (e.g. auto-assign reviewers)
– Tasks could be executed asynchronously easily
• All sending signals live in the questionnaire module, notifications receivers in the notifications module.

View

• Heavily built for asynchronous calls. This is due to heavy queries.


• JS is mostly in the file `static/notifications/js/notificationActions.js`
• Some logic for the filters depends on the get querystring.

Logic

• Most of the logic is in the `ActionContextQuerySet`, so it is reusable.


• The text for a notifications subject depends on its action and is based on the template `templates/
notifications/subject/<action>.html`

Mails

• No mails are sent yet, as the texts and triggers are not stable.

qcat

The Django app qcat contains the basic settings and functions of the entire QCAT application.

qcat.utils

questionnaire

The Django app questionnaire is responsible for the questionnaires and their versions.

7.3. Code 71
QCAT Documentation, Release 0.1.0

questionnaire.models

questionnaire.upload

questionnaire.urls

questionnaire.utils

questionnaire.views

Summary

This describes the ideas and workflow of how questionnaires are exported as pdf. As of now, there is only one type of
summary which displays the questionnaire in full - so its not actually a summary but just a pdf-export.
Following changes are planned:
• Users should be able to select/deselect sections in the pdf (description, location, etc.). So editing the markup
before creating the PDF will be required.
• Changes in the output format (paper formats, fields on display) should be configurable.

Idea and rationale

The summary is not a fixed (hard coded) view, but its content may change depending on configuration and version of
the config.
The relevant sections for the summary of each questionnaire are defined in the config. Gathering data for the summary
happens in two steps:
• Parser: get combined data from config and questionnaire (use the same functionality as the questionnaire API
resource)
• Renderer: filter, aggregate and annotate data specifically for the summary
The naming (parser and renderer) is not 100% precise, but indicates the idea.
The created HTML is then converted to PDF with wkhtmltopdf.
This concept was decided upon because:
• Frontend work can be sourced to external colleagues
• Robust handling of data (questionnaires and configs will change)
• More summary types can be added later
• HTML can be converted to different formats (doc) as well
• The very first step of combining data from config and questionnaire was required for another project as well
(API)

Technical workflow

• The view `summary.views.QuestionnaireSummaryPDFCreateView` is called


• Data for the summary is created with the defined renderer in `summary.renderers`. This renderer set up
the data by the according to summary type and configuration.

72 Chapter 7. Hosting
QCAT Documentation, Release 0.1.0

• In the parser module (`summary.parsers`), questionnaire and configuration data is com-


bined with the same class built for the questionnaire detail API resource: `configuration.
configured_questionnaire.ConfiguredQuestionnaire`
• The full data is then prepared as defined in the configuration.
• The initial idea was to define each question which must appear in the summary. This ‘whitelisting’ is not always
a good fit due to repeating questions/ questiongroups. Therefore, specific data preparation methods are available
on the parsers classes.

Add a new summary type

• Either subclass `summary.views.SummaryPDFCreateView` with a custom summary-type, or refactor


the class for dynamic usage via get param or such.
• Define a renderer in `summary.views.SummaryPDFCreateView.render_classes`
• A new template may be created (`summary.templates.layout`) and can be passed as GET-parameter
to the view.
• Extend or create the renderer and according templates

Add a new field

• In the fixtures-json file, find the desired question and add the summay-config to the ‘configuration’ value (see
examples below).
• Depending on the complexity of the question(s) involved, a specific data loading method on the parser may be
required (but is optional).
• For most questions, the default data loading is fine - simply add the field on the respective renderer.
• Minimal example

"configuration": {
"type": "radio",
"summary": { # summary config starts here
"types": ["full"], # list with all summary-types
"default": {
"field_name": "some_name" # the key which will be used for this data in
˓→the summary

}
}
}

• Full example

"configuration": {
"type": "radio",
"summary": {
"types": ["full"],
"default": {
"field_name": {
"qg_31.question_keyword": "field_name_one", # when the same question is
˓→used in multiple questiongroups:

"qg_97.question_keyword": "field_name_two" # provide different access-


˓→keys in the summary

},

7.3. Code 73
QCAT Documentation, Release 0.1.0

"get_value": { # use a custom method on the


˓→ parser
"name": "get_qg_values_with_scale", # name of the method
"kwargs": {
"qg_style": "radio" # additional kwargs passed
˓→to the method

}
}
}
}
}

History

• It was planned to pass JSON to the frontend and do all conversion to html with handlebars. This was rejected
from we are cube with regard to technical feasibility.
• wkhtmltopdf was selected based on a demo-HTML / proof of concept.

unccd

The Django app unccd contains the configuration for the UNCCD questionnaire.

unccd.views

74 Chapter 7. Hosting
CHAPTER 8

Indices and tables

• genindex
• modindex
• search

8.1 To Do’s

This page contains a list of all To Do’s that emerged during the development process. The list may be rather unordered
because the To Do’s are specified directly in the code.

Todo: Questionnaire configurations can inherit from another one. This needs further documentation.

(The original entry is located in /home/docs/checkouts/readthedocs.org/user_builds/qcat/checkouts/latest/docs/configuration/introduction


line 59.)

Todo: This does not really belong here

(The original entry is located in /home/docs/checkouts/readthedocs.org/user_builds/qcat/checkouts/latest/docs/development/dataformat.rs


line 129.)

75
QCAT Documentation, Release 0.1.0

76 Chapter 8. Indices and tables


Index

U
User Group, 3
User Groups, 3

W
WOCAT, 3

77

You might also like