formly
is a forms/survey generator for dynamically constructed multi-page surveys with the ability to be non-linear.
formly
is an app that provides an out of the box solution to building adhoc
forms to collect data from end users. It is multi-faceted in that it provides
interfaces for building multi-page forms, interfaces for executing the survey,
as well as views for reviewing results.
Also, it is non-linear, meaning that you can route users taking the survey to different pages based on what they answered on certain questions. This allows you to create very rich surveys that dive deep on detail you care about while not wasting the time of users who would otherwise have to go through questions that do not apply to them.
Development sponsored by Midwest Communications and Massachusetts General Hospital.
Django \ Python | 3.6 |
---|---|
2.2 | * |
3.1 | * |
To install formly:
$ pip install formly
Add formly
to your INSTALLED_APPS
setting:
INSTALLED_APPS = [
# other apps
"formly",
]
Next, add formly.urls
to your project urlpatterns:
urlpatterns = [
# other urls
url(r"^surveys/", include("formly.urls", namespace="formly")),
]
Finally, if you want to use formly's permission authentications,
add formly.auth_backend.AuthenticationBackend
to your settings
AUTHENTICATION_BACKENDS:
AUTHENTICATION_BACKENDS = [
# other authentication backends
"formly.auth_backend.AuthenticationBackend",
]
In order to use built-in templates, add the following dependencies to your project:
INSTALLED_APPS = [
# other apps
"bootstrapform",
]
formly
is designed to be plug-and-play, in that after you install formly
using it should be as simple as creating and publishing surveys through
the web interface.
After installation, browse to wherever you mounted the urls for formly
and
you'll see an interface to be able to create a new survey. From here you can
create a survey and begin editing pages. Pages in formly
represent each
step of the survey. The user will be guided through each page of the survey
in the appropriate order saving each page at a time.
For each page, you can give a title and add as many fields as you desire. If the field is a type that requires choices, then you will have the option on the fields detail/edit form to add choices. An optional value that can be supplied for a choice answer is the page to redirect the user to if they select that answer.
If you have multiple choice fields in a single page with conflicting page
routing, formly
resolves to the first page it encounters. For example, if
you had a question that had choice B route to page 3 and another question
later in the form that had choice C route to page 5 and the user answered
both questions with choice B and choice C, the user would go to page 3
next. Keep this in mind when building surveys.
formly
enables you to create questions with a multitude of field types that
will control the dynamic rendering and processing of form input on each page of
your survey.
All field types tie directly to a specific field
and widget
configuration as found in django.forms
. The other attributes that can be
passed into every field, label
, help_text
, and required
can be
set and managed at design time.
For the field types that accept choices, there is the ability to set key/value pairs for each field that are used to populate the choices attribute for the field to be used for both display as well as form validation upon execution.
Renders and processes input using django.forms.BooleanField
.
A field generated from a django.forms.MultipleChoiceField
with a
django.forms.CheckboxInput
widget, populated with choices specified
at design time. This field allows for multiple selections.
Provides a way to constrain input to dates only. It is
generated from a django.forms.DateField
.
A django.forms.ChoiceField
populated with choices specified at design time.
The field template formly/templates/bootstrapform/field.html
emits:
<ul class="likert-question">
{{ field }}
</ul>
for hooking in CSS design. The following sample CSS presents a Likert field in familiar horizontal layout. You should add this (or similar) CSS to your project to get Likert-scale presentation.
form .likert-question {
list-style:none;
width:100%;
margin:0;
padding:0 0 35px;
display:block;
border-bottom:2px solid #efefef;
}
form .likert-question:last-of-type {
border-bottom:0;
}
form .likert-question:before {
content: '';
position:relative;
top:13px;
left:13%;
display:block;
background-color:#dfdfdf;
height:4px;
width:75%;
}
form .likert-question li {
display:inline-block;
width:19%;
text-align:center;
vertical-align: top;
}
form .likert-question li input[type=radio] {
display:block;
position:relative;
top:0;
left:50%;
margin-left:-6px;
}
form .likert-question li label {
width:100%;
}
Enables users to upload content as a response using django.forms.FileField
.
Presents a number of single line fields. The number of fields is specified at design time.
A django.forms.ChoiceField
with a django.forms.RadioSelect
widget,
populated with choices specified at design time.
A django.forms.ChoiceField
populated with choices specified at design time.
The field template formly/templates/bootstrapform/field.html
emits:
<ul class="rating-question">
{{ field }}
</ul>
A select field generated from a django.forms.ChoiceField
with a
django.forms.Select
widget, populated with choices specified at design time.
A field for open ended text input and is interpreted as django.forms.CharField
.
A django.forms.CharField
with a django.forms.Textarea
widget used
to collect longer form text input.
formly
ships with some stock templates that are based on
pinax-theme-bootstrap
and django-forms-bootstrap
. You are not required
to use these of course and in case you are rolling your own templates, here
is what the views in formly
expect.
formly/design/choice_form.html
Context: form
, choice
, page
Extends: formly/design/survey_edit_base.html
Provides the ability to update the values for a particular choice for a choice field.
formly/design/field_confirm_delete.html
Context: form
, field
Extends: site_base.html
Rendered to supply a delete confirmation form for field deletion.
formly/design/field_form.html
Context: form
, field
, page
, field_choice_form
Extends: formly/design/survey_edit_base.html
Rendered for a user interface to update a field.
formly/design/fieldchoice_confirm_delete.html
Context: form
, fieldchoice
Extends: site_base.html
Rendered to supply a delete confirmation form for field choice deletion.
formly/design/page_confirm_delete.html
Context: form
, page
Extends: site_base.html
Rendered to supply a delete confirmation form for page deletion.
formly/design/page_form.html
Context: form
, page
, field_form
Extends: formly/design/survey_edit_base.html
Displays the user interface for updating a page object.
formly/design/survey_confirm_delete.html
Context: form
, survey
Extends: site_base.html
Rendered to supply a delete confirmation form for survey deletion.
formly/design/survey_detail.html
Context: survey
Extends: site_base.html
Displays the detail for a survey.
formly/design/survey_edit_base.html
Context: page
Extends: subnav_base.html
Extended By: formly/design/choice_form.html
, formly/design/field_form.html
, formly/design/page_form.html
A base template to provide common sub-navigation.
formly/design/survey_form.html
Context: form
Extends: site_base.html
Contains the creation form for creating a new survey object.
formly/design/survey_list.html
Context: unpublished_surveys
, published_surveys
Extends: site_base.html
This template receives all surveys in the system split between two context objects, one for published surveys and the other for unpublished surveys.
formly/results/home.html
Context: survey
Extends: site_base.html
Displays the results of a given survey.
formly/run/page.html
Context: form
, page
Extends: site_base.html
Rendered for the end user to complete a particular survey. Always rendered with the appropriate page for the user.
formly/results/remap.html
Context: field
, unmapped_answers
, answer_string
Extends: site_base.html
Allows the end user to "remap" answers for a MULTI_TEXT
field, e.g.
# User A's answers to the question,
# "What are your favorite Central City establishments?"
Big Belly Burger
Star Labs
Jitters
# Answers for User B
Big Belty Burger
STAR labs
Palmer Technologies
Passing Big Belly Burger
as the answer_string
URL argument would allow
the end user to map Big Belty Burger
as an answer to Big Belly Burger
.
formly/bootstrapform/field.html
Context: field
This modified django-bootstrap-form
template renders the various field types,
including special handling for Likert and Rating fields.
formly
ships with an auth backend that by default, when added to
your AUTHENTICATION_BACKENDS
setting will segment the create,
edit, delete and results viewing based on request.user
being
the Survey.creator
.
You can override this by writing your own auth backend and using in it's place.
The permission labels used are as follows:
formly.view_survey_list
User can see the list of published and unpublished surveys.
formly.create_survey
User can create a survey.
formly.view_survey_detail
User can view the survey's detail. The survey object in question is
passed to the has_perm
method of the auth backend.
formly.change_survey_name
User can change the survey's name. The survey object in question is
passed to the has_perm
method of the auth backend.
formly.publish_survey
User can publish the survey. The survey object in question is
passed to the has_perm
method of the auth backend.
formly.duplicate_survey
User can duplicate the survey. The survey object in question is
passed to the has_perm
method of the auth backend.
formly.edit_survey
User can edit the survey. The survey object in question is
passed to the has_perm
method of the auth backend.
formly.view_results
User can view the survey's results. The survey object in question is
passed to the has_perm
method of the auth backend.
formly.delete_object
User can delete the object in question. The object will be either a
Survey
, Page
, Field
, or a FieldChoice
.
Callbacks are a way to provide functionality to formly
that requires some
runtime decision making instead of just a setting. They are callables
defined in settings.py and ship some sane defaults.
FORMLY_COMPLETE_REDIRECT_CALLBACK
Default: formly.callbacks.survey_complete_redirect
Arguments: survey
Expected Return: a url that will be passed to redirect()
TBD
Backwards Incompatible Changes Drops support for Python 2.x and Django 1.x.
MULTIPLE_TEXT
answersFORMLY_TEST_ARGS
pattern to run a restricted version of the test suiteBackwards Incompatible Changes
Previously, answers stored in FieldResult.answer
for Field
s with the MULTIPLE_TEXT
field_type were getting serialized to JSON twice.
This release fixes this by:
compress
and decompress
methods in the form field / widgetCopyright (c) 2012-2018 Patrick Altman and contributors under the BSD license.