Reactive Data Management for NiceGUI with Tortoise ORM
Project description
nicegui-rdm: Reactive Data Management
Why: in a nutshell
ng_rdm offers a clean and modern set of (non-Quasar) tables with all the plumbing you need to build database-backed NiceGUI applications. Moreover, these tables can automatically refresh when back-end data is added or modified. Hence: reactive data management.
Background (feel free to skip)
ng_rdm is based on two ideas:
-
For my own apps I needed to add reactivity to database applications: changes in data should be reflected in UI components, without the user having to refresh a page. Imagine a table showing items, counts, stock being updated in near real-time as data is changing. This is the core of the library, implemented in
modelsandstore. Note: this is similar to but complementary to the reactivity we can easily achieve ‘client-side’ with NiceGUI bindings etc. -
Secondly, I've always been fighting Quasar's “composite” UI components such as tables, dialogs, cards, etc.: layer upon layer of div's and the most obnoxious CSS imaginable. Thanks to NiceGUI's websocket architecture we can move the logic for and behavior of those components from JavaScript/VueJS over to the Python side. In
components/widgetsyou'll find tables that create clean html with semantic CSS selectors and that tie in tostoreobservability – entirely in Python.
See below for a more detailed overview of the architecture.
Installation
pip install nicegui-rdm
Architecture
┌──────────────────────────────────────────────────────────┐
│ UI Components │
│ ActionButtonTable · ListTable · SelectionTable │
│ EditDialog · EditCard · DetailCard · ViewStack │
└──────────────┬─────────────────────────────────┬─────────┘
│ 1. user action ▲
▼ │ 6. notify_observers
┌──────────────┴─────────────────────────────────┴─────────┐
│ Store Layer │
│ Store (base) · DictStore · TortoiseStore │
│ MultitenantTortoiseStore · StoreRegistry │
│ CRUD · validation · observer pattern │
└──────────────┬─────────────────────────────────┬─────────┘
│ 2. validate & write ▲
▼ │ 5. return result
┌──────────────┴─────────────────────────────────┴─────────┐
│ Data Layer │
│ Tortoise ORM · QModel │
│ SQLite · PostgreSQL · MySQL │
└──────────────────────────────────────────────────────────┘
User actions flow down through the Store layer (which validates and normalizes) to the database. On success, the Store broadcasts a StoreEvent up to all subscribed UI components, which automatically rebuild via @ui.refreshable_method. This is the reactive loop that keeps tables and detail views in sync with the database without manual refresh.
Quick Start
from nicegui import app, ui
from tortoise import fields
from ng_rdm import TortoiseStore, init_db, close_db, FieldSpec, Validator
from ng_rdm.models import QModel
from ng_rdm.components import (
rdm_init, Column, TableConfig, FormConfig,
ActionButtonTable, EditDialog,
)
# 1. Define a model with validation
class Task(QModel):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=100)
field_specs = {
"name": FieldSpec(validators=[
Validator("Name is required", lambda v, _: bool(v and v.strip()))
])
}
# 2. Initialize database and create a store (module level)
init_db(app, "sqlite://tasks.db", modules={"models": [__name__]}, generate_schemas=True)
app.on_shutdown(close_db)
task_store = TortoiseStore(Task)
# 3. Build a page
@ui.page("/")
async def index():
rdm_init() # load CSS + Bootstrap Icons
columns = [Column("name", "Task name")]
table_config = TableConfig(columns=columns)
form_config = FormConfig(columns=columns, title_add="New Task", title_edit="Edit Task")
# EditDialog for add/edit; ActionButtonTable for display
dlg = EditDialog(data_source=task_store, config=form_config,
on_saved=lambda _: table.build.refresh())
table = ActionButtonTable(
data_source=task_store, config=table_config,
on_add=dlg.open_for_new, on_edit=dlg.open_for_edit,
)
await table.build()
ui.run()
What's Included
Tables — ActionButtonTable (CRUD with per-row action buttons), ListTable (read-only clickable rows), SelectionTable (checkbox multi-select)
Forms — EditDialog (modal create/edit), EditCard (inline form)
Navigation — ViewStack (list/detail/edit flow), Tabs (tabbed content)
Display — DetailCard (read-only detail view), Dialog (modal overlay), StepWizard (multi-step form)
Layout — Button, IconButton, Icon, Row, Col, Separator
Store layer — DictStore (in-memory), TortoiseStore (ORM-backed), MultitenantTortoiseStore (tenant-scoped)
See components/API.md for the full component API reference.
Examples
Run any example with python -m ng_rdm.examples.<name> and open http://localhost:8080.
| Example | Description |
|---|---|
catalog |
Component catalog — showcases all widgets |
master_detail |
ViewStack master-detail navigation |
custom_datasource |
Custom RdmDataSource implementation |
vanilla_store |
Basic store usage without UI components |
topic_filtering |
Topic-based observer filtering |
Some notes
Requirements
- Python 3.12+
- NiceGUI >= 1.4.0
- Tortoise ORM >= 0.20.0
- pytz
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nicegui_rdm-0.1.0.tar.gz.
File metadata
- Download URL: nicegui_rdm-0.1.0.tar.gz
- Upload date:
- Size: 81.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a5ff3c0ed960917232ffb59cc0b40933b0e940dfb3953d305ec229584954eb11
|
|
| MD5 |
dad90e4f3312883ada9f4416048f6da7
|
|
| BLAKE2b-256 |
0f8c7d42f30b29a289a88e1a1dadc9169c82321eb85c30af0efd7e5494fc17e3
|
File details
Details for the file nicegui_rdm-0.1.0-py3-none-any.whl.
File metadata
- Download URL: nicegui_rdm-0.1.0-py3-none-any.whl
- Upload date:
- Size: 82.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ee6149bedc993235ea27b0dc8f8c148d4165f96ba454e1a17344fae27c19d693
|
|
| MD5 |
6b28558d47f57ffef72c7d6a1d6d19e9
|
|
| BLAKE2b-256 |
69655060d509153f3544be1408ccdfe43f1ee84e33e8dbb2afed9174486cbf7b
|