Skip to content

signebedi/libreforms-fastapi

Repository files navigation

libreforms-fastapi

FastAPI implementation of the libreForms spec

Getting Started

Follow the steps below to install the system on your computer. Please note, you need to install Python3.10 (or higher) and Python3.10-Venv through your package manager. If you plan to use MongoDB and a relational database, you will need to install these, too. See your distribution's specific instructions for these steps or install using Docker to get started.

cd /opt/libreforms-fastapi
python3 -m venv venv
source venv/bin/activate
pip install libreforms_fastapi
uvicorn libreforms_fastapi.app:app --reload # this will run the development server

You can also install manually using the git repository, which is recommended for development.

git clone https://github.com/signebedi/libreforms-fastapi.git
cd libreforms-fastapi
python3 -m venv venv
source venv/bin/activate
pip install -e .
uvicorn libreforms_fastapi.app:app --reload # this will run the development server

Installing Extras

If you want to also enable the use data science libraries and Excel exports, you should pip install using the data extras tag.

pip install libreforms_fastapi[data]

If you plan to use Postgres or MariaDB, then there are additional extras tags for those, too.

pip install libreforms_fastapi[postgres] # for Postgres
pip install libreforms_fastapi[mariadb] # for MariaDB

Running in Production

To run in production, you need to generate an app configuration and daemonize uvicorn. If this sounds too daunting, consider running the Docker container. If you're not dissuaded, you can use the CLI. After pip installing the package, you can use the libreformsctl command to get the application running in production. Here's an example:

libreformsctl config production
libreformsctl uvicorn --environment production 
libreformsctl nginx production # Optional if you want a reverse proxy 

Troubleshooting Errors

You may sometimes run into inexplicable runtime errors. These often result from permission issues on the filesystem. When in doubt, try running the following command as root on your project root directory (below, we've selected /opt/libreforms_fastapi).

chown -R fastapi:fastapi /opt/libreforms_fastapi

Running in Docker

Follow the instructions below to run in docker. Creating a custom volume is optional but will give you control over the application configurations and, in the event you are using TinyDB and SQLite, you will also be able to access the database files.

git clone https://github.com/signebedi/libreforms-fastapi.git
cd libreforms-fastapi/
sudo docker build -t libreforms-fastapi . # Please note this can take several minutes
sudo docker volume create libreforms-volume # Create a volume for the instance directory
sudo docker run -d --name libreforms-instance -v libreforms-volume:/app/instance -p 8000:8000 libreforms-fastapi

You can create an admin account by running the following commands, being careful to replace <environment> with the appropriate environment (when in doubt, use development). Follow the instructions from the interface that pops up.

sudo docker exec -it libreforms-instance libreformsctl useradd --environment <environment> --site-admin

To stop your instance, you can run the following command.

docker kill libreforms-instance

Configuring Your First Form

The form configuration file uses YAML to define the structure and behavior of form fields. Each form is represented as a key under the root, and each field within a form is defined with various parameters specifying its type, label, default values, validation rules, and other attributes. Here’s an example form configuration in YAML:

example_form:

    text_input:
        input_type: text
        output_type: !str
        field_label: Text Input
        default: Default Text
        validators:
            min_length: 1
            max_length: 200
        required: true
        description: A text input field

    number_input:
        input_type: number
        output_type: !int
        field_label: Number Input
        default: 42
        validators:
            ge: 0
            le: 10000
        required: false
        description: A number input field

    checkbox_input:
        input_type: checkbox
        output_type: !list
        field_label: Checkbox Input
        options:
            - Option1
            - Option2
            - Option3
        required: true
        default:
            - Option1
            - Option3
        description: A checkbox input field

another_form:

    section_header:
        is_header: true
        field_label: Section Header
        description: This is an example of a section header. You can put as much text here as you need to guide users in the submission of the form in the UI.

    select_input:
        input_type: select
        output_type: !str
        field_label: Select a user
        options: !all_usernames_by_group_default
        required: true
        description: A select input field, illustrating how to use data retrieval tags.
Field Parameters

Each field configuration includes several key parameters:

  • input_type: Specifies the type of input control to use, such as text, number, email, checkbox, radio, select, etc.
  • output_type: Indicates the data type for the field’s output, using custom YAML tags like !str, !int, !list, etc.
  • field_label: A user-friendly label for the field, which will be displayed on the form.
  • default: The default value to populate the field when the form loads.
  • required: A boolean indicating whether the field must be filled out for form submission.
  • options: Available choices for fields like select, radio, and checkbox inputs. This can be a static list or dynamically populated using special YAML tags.
  • description: A brief description of the field, providing context or instructions for users.
  • validators: A set of validation rules for the field, defining constraints like minimum and maximum length, patterns, and numerical limits. These are drawn from pydantic Fields.
Adding Headers

Headers are special fields in the YAML configuration used to group related fields or provide context within the form. Unlike standard fields, headers do not capture user input but serve to organize the form layout and help guide users. Headers support fewer parameters compared to input fields since they primarily focus on labeling and organizing.

  • is_header: Indicates that the field is a header. This is typically set to true.
  • field_label: The label or title of the header. It acts as a section title or heading in the form.
  • description: A brief description or subtitle for the header, providing additional context or information about the section.
Complex Input Types

In addition to the basic input types described above, the form configuration supports complex input types that provide additional functionality and control over form behavior. These are generally intended to address specific use cases common in form softwares.

First, hidden fields are used to store data that should not be visible or editable by the user. They are often used to hold metadata or other values that need to be submitted with the form but should not be altered by the user. This field comes with the secondary_input_type parameter, which defaults to "hidden" and defines an alternative input type to use when the form is being updated. This allows hidden fields to be shown as editable fields during updates if necessary.

Second, immutable_config fields display data that should not be modified by the user but may be linked to context variables such as request.user or config.SITE_NAME. These fields can be set to be both mutable (eg. update some user value based on a later editor) or hidden under certain conditions. This field comes with various additional parameters. The context_field parameter specifies the context variable to link the field value to, supporting nested context fields like user.username or config.SITE_NAME. This parameter is required. The is_hidden parameter is a boolean that indicates whether the field should be hidden. It is optional and defaults to false. The update_on_edit parameter is a boolean indicating whether the field should become editable when the form is being updated. It defaults to false. Similarly, the update_on_duplicate parameter is a boolean that specifies whether the field should become editable when the form is being duplicated. This parameter defaults to true.

Third, bool_switch fields represent a boolean switch, commonly implemented as a toggle switch with true or false values. The behavior of this input type includes additional parameters and a specific handling of the default parameter. The true_label and false_label parameters are optional and define the labels displayed for the "on" and "off" states of the switch, respectively. They default to "true" and "false" if not provided. The default parameter for bool_switch works differently compared to other input types. Instead of directly using the default value, it determines whether the switch should be in the "on" or "off" position. If default is provided and evaluates to true, the switch will be in the "on" position; otherwise, it will be in the "off" position. Passing no value as the default will result in it defaulting to false.

Using YAML Tags

The custom loader supports specific YAML tags to define output types and dynamically retrieve data for select, radio, and checkbox fields in forms. These include output_type tags indicating the expected type of a field's output.

  • !int: Integer value.
  • !str: String value.
  • !date: Date value.
  • !datetime: Datetime value.
  • !time: Time value.
  • !timedelta: Time delta value.
  • !list: List value.
  • !tuple: Tuple value.
  • !bytes: Byte value.
  • !bool: Boolean value,

These also include data retrieval tags that dynamically yield data for form fields such as select, radio, and checkbox inputs.

  • !all_usernames: List of all usernames.
  • !all_usernames_by_group_<group_name>: List of usernames for a specific group (replace <group_name> with the actual group name).
  • !all_groups: List of all group names.
  • !all_submissions_<form_name>: List of form IDs for a specific form type (replace <form_name> with the actual form name).