FastAPI implementation of the libreForms spec
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
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
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
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
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
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.
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.
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.
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
.
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).