Skip to main content

django-unfold-fobi

PyPI - Version Build

Introduction

django-unfold-fobi integrates django-fobi into django-unfold. It provides an Unfold-native admin experience for managing Fobi forms, plus a small compatibility and patch layer for modern Django/DRF stacks.

Intention

This package is an integration layer, not a replacement for standalone Fobi usage. You can still use standard Fobi public forms and existing plugins; this project focuses on making the admin and integration surface fit naturally into Unfold-based back offices.

Features

  • Unfold-native admin integration for Fobi form management.
  • Unfold widget styling applied across Fobi admin/plugin form surfaces.
  • DRF-oriented improvements for Fobi API submissions and handler behavior.
  • Admin workflow enhancements (import/clone/popup behavior, staff editing).
  • Optional Sites extension (unfold_fobi.contrib.sites) for site-scoped forms, queryset scoping, and reusable admin mixins.
  • Optional django CMS plugin (unfold_fobi.contrib.cms) for embedding forms in CMS placeholders, with site-aware form selection.
  • Optional ALTCHA protection (unfold_fobi.contrib.altcha) for proof-of-work anti-bot verification on public form submissions.
  • Fobi AppConfig overrides with AutoField pinning and i18n verbose_name labels for projects using BigAutoField.

Requirements

  • Python >=3.10,<4.0
  • Django >=5.0
  • django-unfold >=0.80.0
  • django-fobi >=0.19
  • django-crispy-forms >=2.0
  • djangorestframework >=3.14
  • django-unfold-modal >=0.1.0

Patches & Compatibility

unfold_fobi applies a few startup patches to keep Fobi integration stable on newer dependency versions:

  • DRF compatibility shim restores rest_framework.fields.set_value for DRF 3.15+ where Fobi still expects it.
  • DRF db_store improvements include active-date enforcement and safer integration behavior.
  • Admin patches align popup/modal responses with Unfold workflows.
  • Additional Fobi patches improve widget consistency, staff editing behavior, and mail sender handler field handling.

Limitations

  • Main focus is DRF + admin integration; this package does not try to redesign every standalone Fobi rendering path.
  • For REST-based usage, you need to implement your own frontend form rendering using the API metadata returned for each form.
  • Non-Unfold form rendering should still work, but may not be styled like Unfold unless your project applies matching templates/styles.
  • Form wizards are currently linked/redirected, but not fully covered as a first-class Unfold-integrated workflow.

Quickstart

Install and enable the integration with minimum settings.

  1. Install package:
pip install django-unfold-fobi
  1. Add apps (order matters):
INSTALLED_APPS = [
    "unfold",  # must be before django.contrib.admin
    "crispy_forms",
    "fobi.contrib.themes.simple",
    "unfold_fobi",
    # If using DEFAULT_AUTO_FIELD = "BigAutoField", use these instead of
    # bare "fobi" and "fobi.contrib.plugins.form_handlers.db_store":
    "unfold_fobi.fobi_app_configs.FobiConfig",
    "unfold_fobi.fobi_app_configs.FobiDbStoreConfig",
]
  1. Add required template hooks:
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.request",
                "fobi.context_processors.theme",
                "unfold_fobi.context_processors.admin_site",
            ],
            "builtins": [
                "unfold_fobi.templatetags.unfold_fobi_tags",
            ],
        },
    },
]
  1. Enable theme settings:
FOBI_THEME = "unfold"
FOBI_DEFAULT_THEME = "unfold"

CRISPY_TEMPLATE_PACK = "unfold_crispy"
CRISPY_ALLOWED_TEMPLATE_PACKS = ["unfold_crispy"]
  1. Add URLs (keep admin/fobi/ before admin.site.urls):
from django.urls import include, path

urlpatterns = [
    path("api/", include("fobi.contrib.apps.drf_integration.urls")),
    path("api/", include("unfold_fobi.api.urls")),
    path("fobi/", include("unfold_fobi.urls.public")),
    path("admin/fobi/", include("unfold_fobi.urls.admin")),
]
  1. Run migrations:
python manage.py migrate

Comprehensive Installation Guide

Use this when you need the full integration, including optional Sites support.

1) Install and baseline setup

  • Follow standard django-fobi installation first (plugins, handlers, base settings).
  • Then add unfold_fobi and the Quickstart settings from above.

2) Optional Sites integration

Enable only if your project needs form-to-site bindings.

INSTALLED_APPS += [
    "django.contrib.sites",
    "unfold_fobi.contrib.sites",
]

SITE_ID = 1
UNFOLD_FOBI_SITES_FOR_USER = "myproject.site_permissions.sites_for_user"

Then re-register your form admins with the mixins from unfold_fobi.contrib.sites.admin:

  • SiteAwareFormEntryMixin
  • RelationSiteScopeAdminMixin

These provide site assignment UI, queryset scoping, and reusable site-scoped permission helpers. Your project still owns user-to-site policy and project-specific permission decisions.

3) Optional django CMS plugin

Enable only if your project uses django CMS and wants to embed Fobi forms in CMS placeholders.

Requires django-unfold-extra>=0.2.1.

INSTALLED_APPS += [
    "unfold_fobi.contrib.cms",
]

Then run migrations:

python manage.py migrate

The plugin appears as "Form" (module "Forms") in the CMS plugin picker. It renders the selected form using fobi's standard form rendering.

When unfold_fobi.contrib.sites is also enabled, the form selection dropdown is automatically filtered by the current site and the editor's allowed sites.

If djangocms-rest is installed, the plugin serializes the form reference as {"form_entry": {"name": "...", "slug": "..."}} instead of a bare FK integer.

4) Optional ALTCHA protection

Enable to require proof-of-work verification on public form submissions. Only public forms (is_public=True) are protected; non-public/preview forms are unaffected.

Requires the altcha Python package (>=2.0).

pip install altcha
INSTALLED_APPS += [
    "unfold_fobi.contrib.altcha",
]

UNFOLD_FOBI_ALTCHA_HMAC_SECRET = "your-secret-key"  # required to enable

Add the challenge endpoint URL:

urlpatterns += [
    path("api/", include("unfold_fobi.contrib.altcha.urls")),
]

Optional settings:

UNFOLD_FOBI_ALTCHA_MAX_NUMBER = 100_000       # difficulty (default: 100000)
UNFOLD_FOBI_ALTCHA_ALGORITHM = "SHA-256"      # hash algorithm
UNFOLD_FOBI_ALTCHA_FIELD_NAME = "altcha"      # payload field name in PUT body
UNFOLD_FOBI_ALTCHA_CACHE_ALIAS = "default"    # cache backend for replay protection
UNFOLD_FOBI_ALTCHA_CHALLENGE_EXPIRY = 300     # challenge TTL in seconds

How it works:

  1. GET /api/fobi-form-fields/<slug>/ includes an AltchaField entry for public forms when ALTCHA is enabled.
  2. Frontend fetches a challenge from GET /api/altcha-challenge/.
  3. Frontend solves the challenge client-side (e.g. using the altcha web component) and includes the base64 payload as "altcha" in the PUT body.
  4. Backend verifies the payload before processing the form submission. Missing, invalid, expired, or replayed payloads return 400.

5) Content Text WYSIWYG editor

The Fobi content_text plugin renders as an Unfold-styled Trix WYSIWYG editor out of the box. Bleach is widened to keep Trix's output (p, h1–h3, div, s, u, etc.) on save. No setup required.

Optional settings (all unset = full upstream toolbar, no overrides):

# Restrict which buttons appear (subset of the names below).
# Available: p, underline, bold, italic, strike, link,
#            heading1, heading2, heading3, heading4,
#            quote, code, bullet, number, indent, outdent, undo, redo.
UNFOLD_FOBI_CONTENT_TEXT_TOOLBAR_BUTTONS = [
    "bold", "italic", "link", "heading2", "heading3", "bullet", "number",
]

# Ship fully custom toolbar markup. The partial must wrap its content in
# <template id="trix-toolbar">…</template>.
UNFOLD_FOBI_CONTENT_TEXT_TOOLBAR_TEMPLATE = "myproject/trix_toolbar.html"

# Override the bleach allowlist used by ContentTextForm.clean_text. When set,
# the package leaves these alone; pair with the toolbar buttons you keep so
# saved markup matches what the editor can produce.
FOBI_PLUGIN_CONTENT_TEXT_ALLOWED_TAGS = ["a", "b", "br", "em", "li", "ol", "p", "strong", "ul"]
FOBI_PLUGIN_CONTENT_TEXT_ALLOWED_ATTRIBUTES = {"a": ["href", "title", "target", "rel"]}

6) DRF notes

  • Include both Fobi DRF URLs and unfold_fobi.api.urls.
  • Use GET /api/fobi-form-fields/<slug>/ to fetch per-form field metadata (including available field types/widgets/choices) for frontend rendering.
  • Ensure each form has the db_store handler enabled for persisted API submissions.

If your project uses DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField", replace the bare fobi entries in INSTALLED_APPS with the package-provided configs. These pin AutoField (fobi lacks a BigAutoField migration) and add translatable verbose_name labels.

INSTALLED_APPS = [
    # Replace "fobi" with:
    "unfold_fobi.fobi_app_configs.FobiConfig",
    # Replace "fobi.contrib.plugins.form_handlers.db_store" with:
    "unfold_fobi.fobi_app_configs.FobiDbStoreConfig",
]

Notes

  • unfold_fobi.apps.UnfoldFobiConfig.ready() runs during Django app startup and performs integration bootstrap in this order: DRF compatibility shim, Fobi admin re-registration for Unfold, monkey-patches, and signal registration.
  • If you want explicit app config wiring, use this in INSTALLED_APPS:
INSTALLED_APPS = [
    # ...
    "unfold_fobi.apps.UnfoldFobiConfig",
]
  • Startup signals auto-attach a db_store handler to saved forms and deduplicate duplicates created during JSON import.
  • The Unfold theme for Fobi is registered as uid="unfold".

Metadata

Release files for django-unfold-fobi 0.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-unfold-fobi 0.2.3
File Size Uploaded
django_unfold_fobi-0.2.3.tar.gz 13.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-unfold-fobi 0.2.3
File Interpreter ABI Platform
django_unfold_fobi-0.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 102.0 kB

Release files / django_unfold_fobi-0.2.3.tar.gz

Download URL django_unfold_fobi-0.2.3.tar.gz
Size 13.1 kB
Tags Source
SHA-256 checksum
How to use checksums
7324d3ea066b037784e957acd6825d1f006323ecac9cb7929ef5badf935b8450
BLAKE2b-256 checksum
How to use checksums
5a32e864541c91f61542d4ff12cb6239b38ff3b9ab73951b30295893f2fa39e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.16.5 cpython/3.14.5 HTTPX/0.28.1

Release files / django_unfold_fobi-0.2.3-py3-none-any.whl

Download URL django_unfold_fobi-0.2.3-py3-none-any.whl
Size 88.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3678333b229aac7593a728b707520f9c2052faad7fca5924556abd6206244e04
BLAKE2b-256 checksum
How to use checksums
6c42d7e18284146bb50020b6dec5ef95c06d635253296b1c12c557e23d9ac0f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via Hatch/1.16.5 cpython/3.14.5 HTTPX/0.28.1
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page