Skip to main content

sqladmin-inline

SQLAdmin Inline is an extension for sqladmin that brings Django-style inline editing to your SQLAlchemy models. It allows you to manage related records (one-to-many) directly within the parent model's form.

Coverage Status Coverage Status Coverage Status

Works fully offline. Every asset is either bundled with this package (SortableJS, the inline JS/CSS) or already shipped by sqladmin (Bootstrap/Tabler, Font Awesome, jQuery, select2, flatpickr). Nothing is loaded from a CDN, so the admin keeps working inside a VPN or on an isolated network. This is enforced by the test-suite.

Features

  • Add / edit in a modal, bulk delete with confirmation
  • AJAX search, pagination and "Load more"
  • Drag-and-drop ordering (order_field)
  • Layouts: center (under the form) or sidebar (right column)
  • Async and sync SQLAlchemy session makers
  • Same security as sqladmin's edit page: authentication_backend, is_accessible, can_edit, check_can_edit and form_edit_query all apply to inline endpoints
  • Works with sqladmin's base_url and behind reverse proxies (root_path)

Installation

pip install sqladmin-inline

Quick start

from fastapi import FastAPI
from sqladmin import Admin
from sqladmin_inline import InlineModelAdmin, ModelViewWithInlines, setup_inline_routes


class TagInline(InlineModelAdmin, model=Tag):
    inline_label = "Tags"
    icon = "fa-solid fa-tag"
    layout = "sidebar"
    order_field = "position"            # integer column -> drag-and-drop
    column_list = [Tag.name]
    column_searchable_list = [Tag.name]
    form_excluded_columns = [Tag.post, Tag.position]
    page_size = 5


class CommentInline(InlineModelAdmin, model=Comment):
    inline_label = "Comments"
    icon = "fa-solid fa-comments"
    column_default_sort = ("id", True)   # newest first
    column_list = [Comment.body, Comment.author]
    column_labels = {Comment.body: "Text"}
    form_columns = [Comment.body, Comment.author]   # FK select for author
    can_edit = False


class PostAdmin(ModelViewWithInlines, model=Post):
    column_list = [Post.id, Post.title]
    inlines = [TagInline, CommentInline]


app = FastAPI()
admin = Admin(app, engine)
setup_inline_routes(admin)   # registers endpoints, templates and static files
admin.add_view(PostAdmin)

InlineModelAdmin options

Option Default Description
model — Child SQLAlchemy model (class keyword)
fk_attr auto Relationship or column pointing to the parent
identity <model>_inline Set it when a parent has two inlines of the same model
inline_label <Model>s Section title
icon None Icon classes, e.g. "fa-solid fa-tag" (Font Awesome bundled with sqladmin)
layout "center" "center" or "sidebar"
column_list all non-PK columns Columns of the table
column_labels {} Column labels
column_searchable_list [] Columns used by the search box
column_default_sort PK asc (column, descending)
order_field None Integer column for drag-and-drop ordering
page_size 5 Rows per page / per "Load more"
can_create, can_edit, can_delete True Inline permissions
form_columns, form_excluded_columns, form_args, form_widget_args — As in sqladmin.ModelView

If the form contains the relationship to the parent, it is pre-selected when adding a row, and the parent passed in the URL always wins on create. Most projects simply exclude it (form_excluded_columns = [Tag.post]).

HTTP endpoints

All are relative to the admin mount point and protected like the parent's edit page:

GET    /{identity}/inline/{inline}/{parent_pk}/list      table fragment (?page=&search=)
GET    /{identity}/inline/{inline}/{parent_pk}/form      form fragment (?pk= to edit)
POST   /{identity}/inline/{inline}/{parent_pk}/save      create/update (422 + form on errors)
DELETE /{identity}/inline/{inline}/{parent_pk}/delete    {"pks": [...]}
POST   /{identity}/inline/{inline}/{parent_pk}/reorder   {"pks": [...]} in the new order
GET    /_inline/static/...                               bundled JS/CSS

Compatibility

Python ≥ 3.10, SQLAlchemy ≥ 2.0, sqladmin ≥ 0.25 (tested with 0.25, 0.28, 0.30, 0.32). On sqladmin ≥ 0.31 the official edit_context hook is used; older versions get a thin wrapper around the edit route that keeps sqladmin's own handler.

Development

task sync     # uv sync with demo/tests/lint groups
task test     # unit + HTTP + security + offline checks (async and sync sessions)
task e2e      # headless browser test (needs node), external network blocked
task lint     # pre-commit: ruff, black, mypy, bandit
task demo     # http://localhost:8000/admin

Licenses

SortableJS (MIT) is bundled; its license is in sqladmin_inline/statics/licenses/.

Metadata

Release files for sqladmin-inline 0.2.1

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

Source distribution (sdist)

Source distribution for sqladmin-inline 0.2.1
File Size Uploaded
sqladmin_inline-0.2.1.tar.gz 58.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sqladmin-inline 0.2.1
File Interpreter ABI Platform
sqladmin_inline-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 104.4 kB

Release files / sqladmin_inline-0.2.1.tar.gz

Download URL sqladmin_inline-0.2.1.tar.gz
Size 58.9 kB
Tags Source
SHA-256 checksum
How to use checksums
3375925b4d0250f2c086b6311f9d74000444eef2708a991507bfb968fd6c6df4
BLAKE2b-256 checksum
How to use checksums
dc04787118cd450dcdbc9732c2c363366197b45c0272eed7512e5a2bc2d48ef7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.10","id":"questing","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / sqladmin_inline-0.2.1-py3-none-any.whl

Download URL sqladmin_inline-0.2.1-py3-none-any.whl
Size 45.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
15336dfa232123acad3be500c992501fe20d04571fb7dea7908c67173b9fb75c
BLAKE2b-256 checksum
How to use checksums
7629123902053ff9d4b16a6c0d6ce67f21ee528530950c7a6590f127bf9a8873
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"25.10","id":"questing","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

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