Formification
Formification is a Django app for building custom web forms and collecting submissions. Forms are defined and managed from the Django admin, rendered publicly through Django's form framework, and every submission is stored and exportable from the admin interface.
- Dynamic forms — authors compose forms (fields, option lists, validation rules) entirely from the admin UI. No code is required to ship a new form.
- Public rendering — forms render with a Bootstrap 3 stylesheet and plug into standard Django form patterns for easy theming.
- Submission collection — each submission is stored with the form, source page, and metadata; retriable via the admin or the REST API.
- Vue 3 admin — the form builder runs as a checked-in Vue SPA. It ships prebuilt in the wheel, so you don't need Node.js to use Formification.
Installation
pip install formification
Add it to your Django project:
# settings.py
INSTALLED_APPS = [
# ...
"django_filters",
"rest_framework",
"formification",
]
# urls.py
from django.urls import include, path
urlpatterns = [
# ...
path("formification/", include("formification.urls")),
path("admin/", admin.site.urls),
]
Apply the migrations:
python manage.py migrate
python manage.py collectstatic --noinput
Configuration
Set where exported submission CSV files are written:
# settings.py
FORMIFICATION_EXPORT_STORAGE_LOCATION = "/data/shared/assets/formification_exports"
Defining a form
Forms are created in the Django admin (/admin/formification/). After that,
render them with a plain Django form:
from django.shortcuts import redirect, render
from formification.forms import CustomForm
from formification.models import Form
def my_form(request):
formification_form = Form.objects.get(slug="robot-form")
if request.method == "POST":
form = CustomForm(
request.POST,
request=request,
instance_id="form-page-a", # recorded on each submission
form=formification_form,
)
if form.is_valid():
formification_form.create_submission(
form.cleaned_data,
source=form.instance_id,
metadata={"extra-data-1": "some data"},
)
return redirect("form-complete")
else:
form = CustomForm(
request=request,
instance_id="form-page-a",
form=formification_form,
)
return render(request, "my_form.html", {"form": form})
<!-- my_form.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Form</title>
</head>
<body>
{{ form }}
</body>
</html>
Dependencies
Python
- Django >= 4.2, < 7
- Python >= 3.10
- djangorestframework >= 3.15.2
- django-filter >= 24.3
- django-ckeditor >= 6.7
- phonenumbers, pyzipcode, us, nameparser, tzlocal
JavaScript
- The public forms bundle jquery, Bootstrap, and intl-tel-input into a single checked-in bundle, so public-facing forms need no external JavaScript.
- The admin is a Vue 3 SPA. The built bundle is checked in and ships inside
the wheel — installing Formification needs no Node.js runtime. To change
the admin, see the
README.mdinsideformification/static/admin/formification/vue-formification/, then rebuild and commit the updateddist/files. - To change the public form assets, see
formification/static/formification/vite-formification/, then rebuild and commit the updateddist/files.
Development
The internal/ directory is a runnable Django project used to develop and demo
Formification locally. From the repository root:
uv sync
uv run python manage.py migrate
uv run python manage.py runserver 0.0.0.0:8000
uv run python manage.py createsuperuser
Or use the make shortcuts (see the Makefile):
make setup # uv sync
make migrate # apply migrations
make seed # load mock demo data
make run # runserver 0.0.0.0:8000
make lint # black --check + flake8 (mirrors CI)
make e2e # real-browser end-to-end tests (pytest-playwright)
End-to-end tests
The internal/e2e/ suite combines pytest-playwright with pytest-django.
Django manages an isolated test database and a live HTTP server on an available
port, including static files and automatic shutdown. Each test creates its form
and rules using factory_boy factories. Coverage includes conditional required
fields, clearing hidden values, option-group switching, AND/OR rules and rule
precedence, text/numeric/multi-select comparisons, and mobile submission. A
separate admin test creates fields and rules through the Vue editor, reloads and
edits them, then submits the public form. Submissions are verified in the test
database; the development db.sqlite3 is never used.
The editor currently offers is and is_not. Additional model/API operators
(contains, does_not_contain, begins_with, ends_with, greater_than,
less_than, any_selected, and all_selected) are exercised with factory data.
make e2e-setup # one-time: install Playwright's chromium
make e2e # run the suite
Install development dependencies with uv sync. Standard Playwright options
work too, for example uv run pytest --headed --tracing retain-on-failure.
Demo data
make seed loads realistic placeholder data into the local database so you
can get a feel for the app immediately: a superuser (demo, password
demo1234), a rich "Demo Form" with mixed field types, conditional rules,
and sample submissions, plus the public robot-form. It is safe to re-run.
Visit the demo form at http://localhost:8000/ and the admin at
/admin/ (log in as demo / demo1234).
License
Formification is licensed under the MIT License.
Release files for django-formification 1.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_formification-1.2.1.tar.gz | 421.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_formification-1.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 872.2 kB
Release files / django_formification-1.2.1.tar.gz
| Download URL | django_formification-1.2.1.tar.gz |
|---|---|
| Size | 421.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6294ebaac17e358e58e0f919940ca9315965ce7078a686a6220ccfa4eb233f98
|
|
BLAKE2b-256 checksum How to use checksums |
09648ac1e5fcd8ea4e1643071243845d2486d208c9aefaf6a5a0cf9fe41fadcc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency logRelease files / django_formification-1.2.1-py3-none-any.whl
| Download URL | django_formification-1.2.1-py3-none-any.whl |
|---|---|
| Size | 450.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
22c3e014aad86aa4aa8be1918e35d7ce4fc3a56bcd60ac81370de6565a56f9dd
|
|
BLAKE2b-256 checksum How to use checksums |
c4a40575e2b22c4981c50e474b7af9606bbb12a83ff3e88bab0f8329392c69b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.
Transparency log