Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

formkit-ninja

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

formkit-ninja

A Django-Ninja backend to specify FormKit schemas

pipPyPI
Version
2.1
Maintainers
1

Formkit-Ninja

A Django-Ninja framework for FormKit schemas and form submissions

Why

FormKit out of the box has awesome schema support - this lets us integrate FormKit instances as Django models

  • Upload / edit / download basic FormKit schemas
  • Translated "option" values from the Django admin
  • Reorder "options" and schema nodes
  • List and Fetch schemas for different form types

Use

To use, pip install formkit-ninja and add the following to settings INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "formkit_ninja",
    "ninja",
    ...
]

Quick Start for New Users

NEW - Create complete data collection apps with minimal coding!

# 1. Create a FormKit schema
./manage.py create_schema --label "Contact Form"

# 2. Bootstrap a complete Django app
./manage.py bootstrap_app --schema-label "Contact Form" --app-name contacts

# 3. Add to INSTALLED_APPS and migrate
# (Edit settings.py to add 'contacts')
./manage.py makemigrations && ./manage.py migrate

# 4. Start collecting data!
./manage.py runserver

See the Quick Start Guide for a complete walkthrough.

Code Generation

NEW in v0.8.1 - Database-driven code generation! Configure type mappings and field overrides through Django admin without writing Python code.

formkit-ninja can automatically generate Django models, Pydantic schemas, admin classes, and API endpoints from your FormKit schemas.

Database-Driven Configuration

Configure code generation rules through the Django admin:

# Django Admin → Code generation configs
formkit_type = "text"
node_name = "district"
django_type = "ForeignKey"
django_args = {"to": "pnds_data.zDistrict", "on_delete": "models.CASCADE"}

Generates:

# models.py
district = models.ForeignKey("pnds_data.zDistrict", on_delete=models.CASCADE)

Quick Start

Generate code from all schemas in your database:

./manage.py generate_code --app-name myapp --output-dir ./myapp/generated

Generate code for a specific schema:

./manage.py generate_code --app-name myapp --output-dir ./myapp/generated --schema-label "My Form"

Generated Files

The code generator creates the following files:

  • models.py - Django models for groups and repeaters
  • schemas.py - Django Ninja output schemas
  • schemas_in.py - Django Ninja input schemas (Pydantic BaseModel)
  • admin.py - Django admin classes
  • api.py - Django Ninja API endpoints

Extensibility

formkit-ninja provides multiple extension points for customizing code generation:

  • Database-Driven Config: Configure through Django admin (no code needed!) ⭐ NEW
  • Custom Type Converters: Add support for custom FormKit node types
  • Custom NodePath: Extend NodePath with project-specific logic
  • Plugin System: Bundle multiple extensions together
  • Custom Templates: Override Jinja2 templates for generated code

See the Database-Driven Code Generation guide for the new database configuration feature, or the Code Generation Guide for detailed documentation and examples.

API

Formkit-Ninja provides a REST API for managing FormKit schema nodes. The API requires authentication and specific permissions.

Authentication

All API endpoints require:

  • Authentication: User must be logged in (session-based authentication)
  • Permission: User must have the formkit_ninja.change_formkitschemanode permission

Unauthenticated requests receive 401 Unauthorized. Authenticated users without the required permission receive 403 Forbidden.

Endpoints

Create or Update Node

POST /api/formkit/create_or_update_node

Creates a new node or updates an existing one.

Request Body:

  • uuid (optional): UUID of node to update. If omitted, a new node is created.
  • parent_id (optional): UUID of parent node (must be a group or repeater)
  • $formkit: FormKit node type (e.g., "text", "group", "repeater")
  • Other FormKit node properties (label, name, etc.)

Response:

  • 200 OK: Success, returns NodeReturnType with node data
  • 400 Bad Request: Invalid input (e.g., invalid parent, deleted node)
  • 403 Forbidden: Insufficient permissions
  • 404 Not Found: Node with provided UUID does not exist (for updates)
  • 500 Internal Server Error: Server error

Update Behavior:

  • When uuid is provided, the node with that UUID is updated
  • If the node doesn't exist, returns 404 Not Found
  • If the node is inactive (deleted), returns 400 Bad Request
  • Parent-child relationships are automatically created/updated when parent_id is provided

Delete Node

DELETE /api/formkit/delete/{node_id}

Soft deletes a node (sets is_active=False).

Response:

  • 200 OK: Success, returns NodeInactiveType
  • 403 Forbidden: Insufficient permissions
  • 404 Not Found: Node does not exist

Response Formats

All successful responses return consistent data structures:

  • NodeReturnType: For active nodes

    • key: UUID of the node
    • node: FormKit node data
    • last_updated: Timestamp of last change
    • protected: Whether the node is protected from deletion
  • NodeInactiveType: For deleted nodes

    • key: UUID of the node
    • is_active: false
    • last_updated: Timestamp of last change
    • protected: Whether the node is protected
  • FormKitErrors: For error responses

    • errors: List of error messages
    • field_errors: Dictionary of field-specific errors

Validation

The API validates:

  • Parent existence: If parent_id is provided, the parent node must exist and be a group or repeater
  • Node existence: If uuid is provided for updates, the node must exist and be active
  • FormKit type: The $formkit field must be a valid FormKit node type

Test

Pull the repo:

gh repo clone catalpainternational/formkit-ninja
cd formkit-ninja
uv sync

Database Setup

Tests require PostgreSQL due to the pgtrigger dependency. Start a PostgreSQL container before running tests:

# Using Podman (recommended)
podman run -d --name formkit-postgres -p 5434:5432 -e POSTGRES_HOST_AUTH_METHOD=trust docker.io/library/postgres:14-alpine

# OR using Docker
docker run -d --name formkit-postgres -p 5434:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres:14-alpine

Then run tests:

uv run pytest

Playwright

Some tests require playwright. Install it with:

uv run playwright install

Note: For full development setup with real data, see DEVELOPMENT.md.

Lint

Format and lint code using ruff:

# Check formatting
uv run ruff format --check .

# Check linting
uv run ruff check .

For Contributors

Prerequisites

  • Python 3.10-3.14
  • uv for package management
  • Podman or Docker for PostgreSQL database
  • Playwright (for browser-based tests)

Development Workflow

  • Set up the project:

    uv sync
    uv run playwright install
    # Start PostgreSQL (see Database Setup above)
    
  • Run tests:

    uv run pytest
    
  • Check code quality:

    uv run ruff format --check .
    uv run ruff check .
    uv run mypy formkit_ninja
    
  • Test Driven Development (TDD):

    • Write tests before implementing features
    • Ensure new code is covered by tests
    • Use pytest as the testing framework
  • Code Style:

    • Use ruff for formatting and linting
    • Follow Python type hints for all function arguments and return values
    • Adhere to SOLID principles
  • Commit Messages:

Updating 'Protected' Nodes

If a node's been protected you cannot change or delete it. To do so, you'll need to temporarily disable the trigger which is on it.

./manage.py pytrigger disable protect_node_deletes_and_updates Make changes ./manage.py pgtrigger enable protect_node_deletes_and_updates

See the documentation for more details: https://django-pgtrigger.readthedocs.io/en/2.3.0/commands.html?highlight=disable

FAQs

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts