スクリプトのお勉強

「要件もデータも決まらない。でもDBが欲しい」を解決するWebアプリ「TinyGrid」を作った話

投稿日:

1. はじめに:現場の「とりあえずExcel」問題

新しい社内プロジェクトやインフラ基盤の刷新、新規事業のPoCなどを進めるとき、エンジニアなら誰もが一度は次のような状況に直面したことがあるはずです。

「要件もデータ構造もまだ固まっていない。でも、今すぐデータを集めて入力・共有したい」

「とりあえずExcel(またはスプレッドシート)で作っておこう」とシートを作り、メンバーに共有して入力してもらうのは非常に手軽で初動が速いという大きなメリットがあります。

しかし、業務や運用が進むにつれて、必ず次のような壁にぶつかります。

  • 他システムや自動化スクリプトから連携できない(ExcelマクロやCSVパースの保守に苦しむ)
  • 外部から叩けるREST APIが存在しない(curlやWebhookでデータを登録・取得できない)
  • 「じゃあRDBMSでWebアプリ化しよう」とすると初期コストが高すぎる(テーブル設計、マイグレーション、CRUD画面作成…とやっている間に要件が変わり、手戻りになる)

求めているのは、「Excelの気軽さ(白紙からすぐに入力できる体験)を持ちながら、裏側ではRDBMSとして動作し、同時にREST APIでアクセスできるツール」 です。

そんな思いから試作してみたのが、Python製の軽量スプレッドシート型DBアプリケーション 「TinyGrid」 です。


2. TinyGrid とは?

TinyGrid は、NiceGUI + AG Grid + FastAPI + SQLAlchemy をベースに構築された、セルフホスト可能なスプレッドシート型データベースです。

+--------------------------------------------------------------------+
|  TinyGrid Web UI (NiceGUI + AG Grid)                               |
|  - 開いた瞬間に白紙グリッドが起動、即座にセル入力可能                  |
|  - ヘッダのダブルクリックで即時リネーム                               |
|  - 日本語ヘッダ入力 -> LLMが英語キー名(API用)を自動命名              |
|  - `_select:status_状態` などのプレフィックスでUIを動的型付け         |
|  - 多言語対応 (日本語 / 英語 / 中国語)                               |
+--------------------------------------------------------------------+
                                   |
                                   v
+--------------------------------------------------------------------+
|  Backend & REST API (FastAPI + SQLAlchemy + Alembic)               |
|  - プロジェクト/シート/行の完全CRUD APIを自動公開 (/api/v1)           |
|  - Swagger UI (/docs) で即座にテスト・外部システム連携可能            |
|  - SQLite / PostgreSQL / MySQL の JSON カラムに柔軟に永続化          |
|  - 統一マイグレーション機構 (Alembic / manage_db.py)                 |
+--------------------------------------------------------------------+

2.1 ソースコードおよび設定・起動方法

今回作成したソースコード一式は、GitHub にて公開しています。

動作要件

  • Python 3.10 以上 (Python 3.11 / 3.12 推奨)
  • モダンブラウザ (Chrome, Edge, Firefox, Safari など)

インストールと起動手順

リポジトリをクローンし、依存ライブラリをインストールして起動するだけで、すぐに使い始めることができます。

# 1. リポジトリのクローンと移動
git clone https://github.com/KenichiTanino/TinyGrid.git
cd TinyGrid

# 2. 依存ライブラリのインストール
pip install -r requirements.txt

# 3. アプリケーションの起動
python app.py

起動後、ブラウザで以下のURLを開きます。

初回起動時に SQLite データベース(tinygrid.db)が自動生成され、スキーママイグレーションも自動実行されるため、事前のDBセットアップ作業は一切不要です。

設定ファイル (config.toml) のカスタマイズ

プロジェクト直下の config.toml で動作設定を柔軟に調整できます。

  • LLM APIキーの設定 (任意):

    ヘッダ名からの英語キー自動生成をLLMに行わせたい場合、Google Gemini API または OpenAI API のキーを設定します(※未設定でも内蔵の辞書・ルールベース変換でオフライン動作します)。

    [llm]
    gemini_api_key = “YOUR_GEMINI_API_KEY” # または openai_api_key
  • セレクトボックス(選択肢)の追加:

      `_select:カテゴリ名_列名` で利用できる選択肢プリセットを定義できます。

      [select_options.status]
      options = [“稼働”, “待機”, “停止”, “故障”]
  • 本番RDBMS接続:

      SQLite以外の外部データベース(PostgreSQLやMySQL)を利用したい場合は、`database_url` を変更するだけで切り替え可能です。

3. TinyGrid の主要機能・推しポイント

3.1 立ち上げ後すぐに入力できる「白紙グリッド駆動 (Blank Grid Driven)」

多くのノーコード/ローコードツール(Airtable、Baserowなど)は非常に高機能ですが、テーブルを作る際に「プロジェクト名入力」「テーブル名入力」「カラム定義(型選択)」といった複数のモーダルを経由する必要があります。

TinyGridは、「Excelを開いてA1セルから即座に叩き始める感覚」 を重視しました。
アプリを起動すると、事前設定なしで「無題のプロジェクト」と空シートが即座に起動します。

  • 白紙セルへ直接入力: セルをクリックして入力するだけで、リアルタイムにデータベースへ自動保存されます。
  • ヘッダのダブルクリックで即時リネーム: 列ヘッダをダブルクリックするだけでブラウザプロンプトが開き、直感的に列名を変更できます。
  • 自由自在な行・列追加: ツールバーの「+ 行を追加」「+ 列を追加」でいつでも柔軟にテーブルを拡張できます。
  • ヘッダ流し込み作成: スペース区切りのヘッダ文字列を貼り付けるだけで、即座に新しいシートを作成できます。

事前設計に悩むことなく、「まずは入力し始める」ことが可能です。

3.2 日本語ヘッダを書くだけで、LLMが英語APIキーを自動生成

WebアプリやAPIの運用で面倒なのが、「画面上の表示名(日本語)」と「APIやプログラムで扱う識別子(snake_caseの英語名)」のマッピングです。

TinyGridでは、ヘッダに IPv4アドレス(VIP)設置場所 と入力すると、バックグラウンドのLLM(Google Gemini / OpenAI)やルールベース辞書が自動で意味を解釈し、適切な英語キー名を割り振ります

| 日本語ヘッダ名      | 自動生成される英語キー名 (`snake_case`) |
| ------------------- | --------------------------------------- |
| `No`                | `no`                                    |
| `キー番号`          | `key_number`                            |
| `ホスト名`          | `host_name`                             |
| `IPv4アドレス(VIP)` | `ipv4_vip_address`                      |
| `設置場所`          | `location`                              |
| `点検日時`          | `inspection_datetime`                   |
| `稼働フラグ`        | `is_active`                             |

LLM APIキーが未設定の場合でも、内蔵のインフラ・業務特化辞書とルールベース変換がフォールバックとして機能するため、完全オフライン環境でも確実に動作します。


3.3 プレフィックスを付けるだけで、UIが動的に型付けされる

「特定の列はドロップダウン選択にしたい」「日付ピッカーでカレンダーから選ばせたい」という場合も、設定画面を開く必要はありません。列名に接頭辞(プレフィックス)をつけるだけで、AG Gridのセルエディタや表示形式が動的に切り替わります。

画面表示時にはプレフィックスが自動で除去され、データ型に応じた分かりやすいアイコン(🕒、📅、⏰、🔢、💰、🔽 等)が付与されます(文字列型のみアイコンなしでプレーン表示)。

  • ドロップダウン選択:
    • _select:status_状態 → 選択肢(稼働/待機/停止/故障)のセレクトボックスが出現
    • _select:env_環境 → 選択肢(本番/ステージング/検証/開発)が出現
    • 選択肢プリセットは config.toml に自由に追加可能
  • 日付・日時ピッカー:
    • _date_導入日_datetime_点検日時
    • ISO 8601形式(YYYY-MM-DDTHH:MM:SS)への自動正規化および入力バリデーション警告に対応
  • 数値・通貨:
    • _num_ポート番号(数値入力・フィルター対応)、_price_月額費用(右寄せ通貨フォーマット)
  • 真偽値・リンク:
    • _is_稼働中(True/Falseトグル)、_url_管理コンソール(ハイパーリンク)

3.4 画面で作ったシートが、そのままREST APIになる

TinyGridで作成したすべてのプロジェクト・シート・レコードは、すぐにREST APIとして外部公開されます。

FastAPIベースのため、/docs にアクセスすれば、おなじみの Swagger UI が立ち上がり、ブラウザ上で直感的にAPIの動作確認やテストが可能です。

API利用例(レコードの登録と取得)

# レコードの追加 (POST)
# 日本語ヘッダ・英語キーのどちらで送信しても自動正規化されて保存されます
curl -X POST "http://localhost:8080/api/v1/projects/インフラ管理/sheets/サーバ台帳/rows" \
  -H "Content-Type: application/json" \
  -d '{
    "data": {
      "ホスト名": "web-srv-01",
      "IPv4アドレス(VIP)": "192.168.1.100",
      "設置場所": "東京第1DC",
      "状態": "稼働"
    }
  }'

# レコード一覧の取得 (GET)
curl -s "http://localhost:8080/api/v1/projects/インフラ管理/sheets/サーバ台帳/rows?format=formatted"

レスポンス例 (format=formatted)

{
  "project": "インフラ管理",
  "sheet": "サーバ台帳",
  "count": 1,
  "rows": [
    {
      "host_name": "web-srv-01",
      "ipv4_vip_address": "192.168.1.100",
      "location": "東京第1DC",
      "status": "稼働"
    }
  ]
}

AnsibleやCI/CDパイプライン、監視ツールから curl や Python スクリプトで直接データを読み書きできるため、「人間はExcel感覚で入力し、システムはAPIで取得する」 というデータ連携が実現します。


3.5 多言語(i18n)& 本番RDBMS(PostgreSQL/MySQL)マイグレーション対応

現場での実用性を高めるため、以下の本格機能も標準搭載しています。

  • GNU gettext 方式(.mo)による多言語対応:
    • 日本語(デフォルト)のほか、英語(en)および中国語(zh)に完全対応。
    • 設定(config.toml)や画面上のドロップダウンから即座に切り替え可能。
  • Alembic による統一マイグレーション:
    • SQLite だけでなく、本番運用の PostgreSQLMySQL にシームレスに対応。
    • 付属の管理CLI(python manage_db.py migrate)やアプリ起動時の自動マイグレーションにより、チーム開発でも安全にスキーマ管理が行えます。

4. アーキテクチャと実装のこだわり

技術スタック

  • UI フレームワーク: NiceGUI
    • PythonだけでVue/Quasarベースのモダンで反応性の高いSPAを記述可能。
  • グリッドエンジン: AG Grid
    • 高速なセルレンダリング、キーボード操作、インライン編集に対応。
  • API エンジン: FastAPI
    • NiceGUI内部のASGIアプリにルーターをマウントし、Swagger UI (/docs) を完全統合。
  • ORM / データベース: SQLAlchemy + Alembic
    • スキーマレスな動的行データはDBの JSON 型に格納。ヘッダの増減や変更が発生しても ALTER TABLE は不要。
  • LLM連携: Google Gemini API / OpenAI API / 内蔵ルールベース

スキーマ変更が容易なデータモデル設計

RDBMSのテーブル定義を動的生成(CREATE TABLE を動的に発行)する方式を採用すると、カラム削除やリネーム時のトランザクションやマイグレーションの複雑さが爆発します。

TinyGridでは、テーブルメタ情報(カラム定義)を TABLE_SCHEMA に保存し、各行の実データは JSON 型で柔軟に保存するハイブリッドアプローチを採用しました。

1プロジェクトに複数シート

動的レコード

PROJECT

TABLE_SCHEMA

int

id

PK

int

project_id

FK

string

name

シート名 (例: サーバ台帳)

json

columns

カラム定義 [{‘field’:’col_0′,’headerName’:’ホスト名’,’keyName’:’host_name’}]

TABLE_ROW

int

id

PK

int

table_id

FK

json

data

{‘col_0′:’web-01’, ‘col_1′:’192.168.1.1’}

これにより、「リレーショナルDBとしての管理構造(親子関係・検索性)」と「スキーマレスNoSQLの柔軟性」 を両立しています。

5. ユースケース:こんな場面で真価を発揮する

  • ネットワーク・インフラ機器のIPアドレス・VIP割当台帳
    • 現場メンバーが入力した台帳から、Ansibleのインベントリ生成スクリプトがAPI経由で直接最新データを取得。
  • クラウド・オンプレサーバの資産管理・点検チェックリスト
    • 日時やステータスをプレフィックス付きカラムで定義し、バリデーション付きでミスなく統一入力。
  • PoCやハッカソン、新規事業のプロトタイプ開発
    • DB設計に悩む時間をゼロにし、すぐに動く管理画面とREST APIを手に入れる。

6. まとめ

「要件が決まってからDBを作る」のではなく、「データを入れながら要件とスキーマを育て、自然とAPIが出来上がる」

TinyGridは、何かと忙しい、システム開発・インフラ運用における現場の課題を解消するために試作しました。

Pythonエコシステム(NiceGUI + FastAPI + SQLAlchemy)の恩恵により、シンプルで見通しの良いコードベースで構成されています。現場の要件や運用ルールに合わせて自由にカスタマイズ・拡張しやすい設計になっています。

おそらく業務にはいろいろ足りないところがあると思うのでカスタマイズして使用する土台として検討してみてください。

-スクリプトのお勉強
-, , ,

執筆者:

関連記事

no image

GLP-1 メディカルダイエット 58日目

メディカルダイエットして58日目の記録をしておこうと思います。 9回目。 今回は左腹(中部)に打ちました。痛いのはいまだに慣れない。。 土曜にゲットしてした 渋谷に行ってきたが、そこの医院には相変わら …

Django2.2 でのMySQL5.1対応

「対応」と書きながら、思い切り回避ですが。 マイグレーション時のエラー マイグレーションしたら、以下のエラーになりました。 $ pipenv run python3 manage.py migrate …

Pipenv vs Poetry

1. はじめに Pythonでお仕事していると、どうしても、環境設定を行う必要があります。 本番環境で動作するように、設定しなければいけないからです。 いろんな状況はあるでしょうが、私がかかわるプロジ …

暗号モードによる処理時間の違いを測定してみた

はじめに 前回、AESで暗号化する実装をしてみた際、知らない暗号モードが増えたなと思いました。 なので、どの暗号モードを使用すべきかの、判定材料の一つとして、代表的な暗号モードの処理速度を簡単に計って …

PyWebIOでform 入力+ REST API呼び出しを作ってみる

仕事柄、簡単なWebアプリを作りたいと思うことはよくあり、その場合はその場で直せるスクリプトで書きたいとよく思うものです。 すごーく簡単なフォームを非常に簡単に使いたいので、まずは簡単に作れるフレーム …

    google オプトアウト Click here to opt-out.