Skip to main content

fastapi-from-frictionless

Status: Work in Progress — API and generated output are subject to change.

Overview

fastapifromfrictionless is a Python scaffolding tool that reads Frictionless Data Package schema files and generates a fully-functional FastAPI + SQLModel application — including models, CRUD endpoints, and dynamic query support — with no hand-written boilerplate.

The driving goal is to bridge the gap between familiar flat-file workflows (Excel workbooks, CSV files, Frictionless packages) and a production-grade relational database with a queryable REST API. Data stewards continue working in Excel; the package handles ingestion, validation, and API synchronization behind the scenes.

Core capabilities:

  • Generate models.py, app.py, and database.py from *.schema.yaml files
  • Automatic SQLModel class hierarchy per schema (base, table, create, update, public, public-with-relations)
  • Full CRUD + pagination + recent-records endpoints per resource
  • Excel workbook as a data-entry interface — create or update API records from a .xlsx file
  • Frictionless package wraps the workbook for field-level validation before ingestion
  • CLI entry point: fastapifromfrictionless generate <schema-folder>

Requirements

An ASGI server such as uvicorn is required to run the generated application.

Installation

pip install fastapifromfrictionless

For environments that run the generated app (FK query endpoints, geo field types):

pip install "fastapifromfrictionless[app]"

Windows

The base install works on Windows without any prerequisites.

The [app] extra includes geoalchemy2, which requires GDAL. If your schemas use geographic field types, install GDAL first:

GDAL installation guide for Windows

Then install the extra:

pip install "fastapifromfrictionless[app]"

If your schemas do not use geo fields, pip install fastapifromfrictionless is sufficient and no GDAL install is needed.

Unique constraints

Frictionless constraints.unique: true emits a unique constraint on the column:

name: str = Field(unique=True)

The flag is merged into whatever the field already carries, so a foreign key keeps its settings:

sensor_name: str | None = Field(foreign_key="sensor.name", index=True, unique=True)

Primary keys are skipped — already unique, so a second constraint would only add a duplicate index.

This matters for foreign keys. PostgreSQL requires a FK to reference a column with a unique or primary key constraint. If a schema's foreignKeys targets a non-PK column, mark that column unique: true or table creation fails with:

psycopg2.errors.InvalidForeignKey: there is no unique constraint matching given keys
for referenced table "sensor"

SQLite does not enforce this, so such a schema works locally and fails only on a real deployment.

Geo field types

Frictionless geopoint and geojson fields generate a geoalchemy2 column rather than a plain annotation:

location: Any | None = Field(default=None, sa_column=Column(Geometry("POINT")))
footprint: Any = Field(sa_column=Column(Geometry("GEOMETRY"), nullable=False))

These columns require a spatial database. create_db_and_tables() fails on plain SQLite with no such function: RecoverGeometryColumn, because geoalchemy2 emits SpatiaLite calls. The generated database.py defaults to SQLite, so a schema with a geo field needs DATABASE_URL pointed at PostGIS (as in the podman/ stack) or SpatiaLite loaded into SQLite.

Quick Start

1. Generate application files from schemas

Place *.schema.yaml files in a folder (see doc/data/ for examples), then run:

fastapifromfrictionless generate path/to/schemas --output path/to/output

Or from Python:

from fastapifromfrictionless.scaffolding import build_database

build_database(schema_folder="path/to/schemas", db_filename="app.db")

2. Start the generated API

cd path/to/output
uvicorn app:app --reload

3. Generated endpoints

For each schema resource, the generated app exposes the following endpoints (replace {resource} with the schema name, e.g. sensor, location, permit):

Method Path Description
POST /{resource} Create a record
POST /{resource}s/bulk Create many records in a single request (one commit)
GET /{resource}/all List all (paginated: ?offset=0&limit=100)
GET /{resource}/recent Most recent records (?limit=10)
GET /{resource}/{id} Get one by primary key
PATCH /{resource}/{id} Update a record
DELETE /{resource}/{id} Delete a record
GET /{resource}/query Dynamic filter query (FK schemas only)
GET /excel/export Download all data as .xlsx
POST /excel/import Upload and sync an .xlsx workbook

4. Configuration via environment variables

Variable Default Description
DATABASE_URL sqlite:///database.db Database connection URL (overrides SQLite default)
ALLOWED_ORIGINS * Comma-separated CORS allowed origins
API_KEY (required) All requests require X-API-Key: <value> header. App refuses to start if unset unless ALLOW_NO_AUTH=true is also set.
ALLOW_NO_AUTH (unset) Set to true to start the app without API_KEY (dev only — logs a warning, do not use in production)
SCHEMA_FOLDER . Path to *.schema.yaml files (used by Excel import/export)
API_URL http://localhost:8000 Base URL of this app (used by Excel export)

5. Excel data workflow

from fastapifromfrictionless.runtime import (
    empty_excel,
    create_package,
    update_api_from_package,
    dump_to_excel,
)

# Create a blank workbook with one sheet per schema
empty_excel(schema_folder="path/to/schemas", output_filepath="data.xlsx")

# Fill in data, then validate and sync to the API
create_package(folder="path/to/schemas", filename="data.xlsx")
update_api_from_package(api_url="http://localhost:8000", package_file="data.package.yaml")

# Or export all current API data to Excel
dump_to_excel(
    api_url="http://localhost:8000", schema_folder="path/to/schemas", output_filepath="export.xlsx"
)

6. CLI reference

fastapifromfrictionless generate <schema_folder> [options]

Options:
  --output DIR      Output directory (default: current directory)
  --db FILENAME     SQLite database filename (default: database.db)
  --dry-run         Print generated code to stdout without writing files
  --no-models       Skip generating models.py
  --no-app          Skip generating app.py
  --no-db           Skip generating database.py

See doc/quickstart.ipynb for a step-by-step walkthrough of the full deployment workflow.

Deployment

A ready-to-use container deployment lives in podman/. It spins up three containers — PostGIS database, pgAdmin web UI, and the generated FastAPI app — and works with Docker Desktop, Podman, or any docker compose-compatible tool on Linux, macOS, and Windows.

Multiple deployments can run simultaneously on the same machine by assigning each a unique SUBNET_BASE and port set (API_PORT, PGADMIN_PORT, DB_PORT).

The API image uses a two-stage build: Stage 1 installs the code-generator and produces FastAPI source from your schemas; Stage 2 installs only the runtime dependencies and serves the generated app. The pip install layer is cached, so schema-only rebuilds are fast.

cd podman/
cp .env.example .env          # set ports, passwords, and settings
# add *.schema.yaml files to schemas/
docker compose up -d          # or: podman-compose up -d

After schema changes, re-run docker compose build api then docker compose up -d api. To stop and clean up, run docker compose down.

See podman/README.md for full instructions.

Metadata

Release files for fastapifromfrictionless 0.2.22

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

Source distribution (sdist)

Source distribution for fastapifromfrictionless 0.2.22
File Size Uploaded
fastapifromfrictionless-0.2.22.tar.gz 32.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastapifromfrictionless 0.2.22
File Interpreter ABI Platform
fastapifromfrictionless-0.2.22-py3-none-any.whl Python 3 none any Details

Total release size: 58.7 kB

Release files / fastapifromfrictionless-0.2.22.tar.gz

Download URL fastapifromfrictionless-0.2.22.tar.gz
Size 32.5 kB
Tags Source
SHA-256 checksum
How to use checksums
caf1472cb4517aa745f544897791e8a7a8a21134a9c7408eef658e47b2d04f54
BLAKE2b-256 checksum
How to use checksums
3f53758ab50c5fc04d8835c12f02ea6307bd83c83a6c729082ec4c6e53a6ca69
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 16, 2026.

Transparency log

Release files / fastapifromfrictionless-0.2.22-py3-none-any.whl

Download URL fastapifromfrictionless-0.2.22-py3-none-any.whl
Size 26.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4e5eba992867164705f3c98e034c3d9402cbbbb0ae2c91eccc563bd48c68fef3
BLAKE2b-256 checksum
How to use checksums
5a362db283dea94d2214af133d28a878e6bc01558bd72f961e5aab1d57195111
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 16, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.3

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

This release

0.2.22 This release

2 release files

0.2.21

2 release files

0.2.16

2 release files

0.2.15

2 release files

0.2.14

2 release files

0.2.13

2 release files

0.2.12

2 release files

0.2.11

2 release files

0.2.10

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

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