Verónica MartínezAug 14, 2015

Pulpo-Forms: A Django’s dynamic form builder

A while ago we create a dynamic form builder, called pulpo-forms, to use within a Django application. Basically, the idea was to create a user friendly dashboard to allow users to create complex forms and surveys without any programming knowledge.

Let me introduce you to this amazing open-source tool.

The main objective of this tool is to allow anyone to create customized forms and surveys. This need comes from some of our clients who time to time have the necessity of gather information from their clients through surveys.

As you can see in the images below, this tool comes with a very intuitive dashboard in order to manage all the forms and surveys

Dashboard Main Page

Edition Dashboard

Like most Django applications, pulpo-forms is implemented based in Django models.

The main models of pulpo-forms are:

  • Form: this is the main model, states the title, identifying slug and user owner of the form.
  • Version: the purpose of this model is to have versioning of the forms created. It allows the possibility to set a status of the version, the possible status are: Drafts, Published or Expired versions.
  • FormEntry: this model groups the answers given by a user to a form’s version.
  • FieldEntry: this model collects an individual answers to a version’s questions, grouped by Form Entry.
  • FileEntry: model containing the files uploaded in a version. Related to a FieldEntry.

A big component of the application is the definition of field types that can be included in the created forms. This provides flexibility and the possibility to extend the supported fields, and also allows the definition of specific validations that should be checked for answers of that field type.

Field Edition

One of the most relevant features included is the possibility to turn a Django model into a specific field type, where you can have all the entries of that particular table as options of a combo box. So, instead of loading all the options of the question, one by one, you can simply create a new field type, which only needs a few lines of code, and have all those options automatically loaded.

And, since those options are retrieved along with the rest of the form with the current model content, there is no issue with whether the options are old or fully updated. All it takes to add a new field type (in this example, a model field) is:

from pulpo_forms.fieldtypes import ModelField
from pulpo_forms.fieldtypes import FieldFactory
from .models import PulpoUser, Club, Country


class ExampleField(ModelField.ModelField):
    prp_template_name = "usuario/properties.html"
    model = ExampleModel
    name = "ExampleModel"

    def get_assets():
        return ['route_to_field_type_asset/ExampleModel.js']

    def __str__(self):
        return "ExampleModel"

FieldFactory.FieldFactory.register('ExampleModelField', ExampleField)

Another interesting feature is the possibility to add conditional logic to both individual questions and whole pages of the form. This means that questions can be shown or hidden depending on logical conditions configured. This gives a lot of freedom to the user creating the forms, allowing them to create different flows according to the participant’s characteristics and the information that is required.

Field Logic

Field Logic 2

Some basic field types also include built-in statistics, that are immediately available in the dashboard for published versions. Those fields are numeric fields, multiple choice (checkboxes), and single choice fields (combo box).

Numeric Field Statistics

Checkbox Statistics

Combo Statistics

Since the statistics are dynamically created, the entries used to generate them can be filtered according to appropriate conditions, based on the field type. Therefore you can gather more significant data about the answers given. The entries returned for the statistics are those that comply with all the conditions listed (a logical ‘and’ of all the conditions).

Filtering Statistics

Also included in the project is an AngularJS directive to render the forms in any template using only the generated form slug.

Hope you enjoy it and please do not hesitate in contact us if you have any questions