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.0

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.0
File Size Uploaded
sqladmin_inline-0.2.0.tar.gz 58.9 kB Details

Built distribution (wheel)

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

Total release size: 104.4 kB

Release files / sqladmin_inline-0.2.0.tar.gz

Download URL sqladmin_inline-0.2.0.tar.gz
Size 58.9 kB
Tags Source
SHA-256 checksum
How to use checksums
b95f776a891d99299024b35076df8b106c90650b863311401a90c27fd2e75bb8
BLAKE2b-256 checksum
How to use checksums
7d65b2c9e71902d70b25ce148248d1858ce3196943f87f410c6c67241a092a8a
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.0-py3-none-any.whl

Download URL sqladmin_inline-0.2.0-py3-none-any.whl
Size 45.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
10c8a891b35e094cc43bb3573c23ed9b02e09b0c76cad5229f2296e0535d34c3
BLAKE2b-256 checksum
How to use checksums
2908018d2e67ba0f98355b8cf7072671bfeed48fadcea0faa97c0e94cb1615f5
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

0.2.1

2 release files

This release

0.2.0 This release

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