Skip to main content

Questions is a form library that uses the power of SurveyJS for the UI.

Project description

Questions Documentation Status

Questions is a Python form library that uses the power of SurveyJS for the UI. The philosophy behind Questions is that modern form rendering usually requires integrating some complex Javascript widgets anyway, so why not skip the markup generation completely?

In Questions, forms are defined in Python similarly to other form frameworks, but everything on the front end is handled by SurveyJS. This provides a lot of benefits:

  • Nice, integrated UI, with powerful Javascript widgets.

  • SurveyJS is compatible with Angular2, JQuery, KnockoutJS, React and VueJS. Questions makes sure that you get the right files for each version.

  • More than 20 question types, from simple text inputs and dropdowns to elaborate widgets like dynamic panels and checkbox matrices.

  • Multiple look and feel options (themes), including Bootstrap CSS support.

  • Full client side validation (plus server side checking, too).

  • Use simple text expressions in question declarations to control which questions to show depending on the answers to previous ones.

  • Complex forms can be defined easily using class composition.

  • Easy multi-page forms, with no state-keeping headaches.

  • Create forms directly from JSON definitions using SurveyJS form creator.

  • Generate Python code from dynamic JSON import.

  • Minimal code for simple apps. If you just need a form or two, you are set.

  • Zero Javascript code option. If you can use a CDN, no need to install or download any javascript.

  • Out of the box integration with popular third party widgets, like select2 and ckeditor.

  • Supports the creation of tests and quizzes, by defining “correct” answers to the questions, and optionally setting a maximum time to finish.

How the Code Looks

To get a feel for how Questions works, nothing better than looking at a simple example:

from questions import Form
from questions import TextQuestion
from questions import RadioGroupQuestion

class SimpleForm(Form):
    name = TextQuestion()
    email = TextQuestion(input_type="email", required="True")
    favorite_number = TextQuestion(title="What is your favorite number?",
    language = RadioGroupQuestion(title="Favorite Language",
        choices=["Python", "Other"])
    version = RadioGroupQuestion(title="Preferred Python Version",
        choices=["Python 2", "Python 3"],
        visible_if="{language} = 'Python'")

This is a fairly conventional way to define forms, so no surprises here, but look at the way the input_type parameter allows us to use different HTML5 text input methods. Pay special attention to the last line, where we use the visible_if parameter to only show the Python version question if the answer to the language question is “Python”. Defining “live” form behavior in this way is something that is usually out of scope for server side code, but Questions’ SurveyJS integration allows us to do it.

Full Working Multi-page Flask Application

Let’s show how easy things can be if your applications needs are simple. The following is a complete application using the popular Flask web framework:

from flask import Flask
from flask import redirect
from flask import request

from questions import Form
from questions import FormPage
from questions import TextQuestion
from questions import DropdownQuestion

class PageOne(Form):
    name = TextQuestion()
    email = TextQuestion(input_type="email", required="True")

class PageTwo(Form):
    country = DropdownQuestion(choices_by_url={"value_name": "name",
        "url": ""})
    birthdate = TextQuestion(input_type="date")

class Profile(Form):
    page_one = FormPage(PageOne, title="Identification Information")
    page_two = FormPage(PageTwo, title="Additional Information")

app = Flask(__name__)

@app.route("/", methods=("GET",))
def form():
    form = Profile()
    return form.render_html()

@app.route("/", methods=("POST",))
def post():
    form_data = request.get_json()
    # Here, we would save to a database or something
    return redirect("/thanks")

def thanks():
    return "Thanks for your information"

if __name__ == "__main__":

By default, Questions uses a CDN for fetching the Javascript resources, which is why all that is needed to run the above code is installing Flask and Questions. Of course, it is possible to install all the dependencies yourself and configure Questions to use your installation, but sometimes this is all that’s required to get a full working application.

Admittedly, our application doesn’t do much, but we get a working form that you can fill and submit in your browser. See how easy it is to get a multi-page form with navigation buttons. Also, notice how get_json is the only Flask request call we need to get the form data.

As the code shows, defining a multiple page form is very simple, and allows us to keep the form pages logically separated, and even using them independently or in combination with other forms with little additional work.

Finally, take a look at the choices_by_url parameter in the DropdownQuestion, which allows us to get the dropdown choices from separate, restful web services.

License and Documentation


This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.


0.5.0a0 (2020-10-01)

  • First release on PyPI.

0.5.0a1 (2020-12-09)

  • Fix bug that caused Questions to crash when two or more panels were used in one form.

  • Add feature for creating Form subclasses from JSON data.

  • Add screencast to README page.

  • Update docs.

  • Update dependencies to lastest versions.

0.5.0a2 (2020-12-09)

  • Fix bug with form parameters in from_json conversion.

0.5.0a3 (2020-12-10)

  • Make sure jinja templates are included in manifest.

0.7.0a4 (2020-12-13)

  • Update installation docs to mention typing-extensions requirement for Python < 3.8.

  • Use correct default value for allow_clear in sugnature pad.

  • Set type hints to allow localization arrays in visible text properties.

  • Fix bug when generating classes from JSON with dynamic panels.

  • Add string representation methods to main classes.

  • Feature: add console script for generating code for classes created with from_json method.

0.7.0a5 (dev)

  • Unreleased.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

questions-0.7.0a5-py3.8.egg (60.4 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page