Metadata-Version: 2.4
Name: django-grid-view
Version: 1.2.0
Summary: Declarative grid views for Django: Simple Table, AG-Grid helpers, KPI cards, ECharts, and an LLM-friendly GridViewSpec contract
Author-email: Oleksii Pylypchuk <alpi@keemail.me>
License-Expression: MIT
Project-URL: Homepage, https://github.com/alpiua/django-grid-view
Project-URL: Repository, https://github.com/alpiua/django-grid-view
Project-URL: Documentation, https://alpiua.github.io/django-grid-view/
Project-URL: Issues, https://github.com/alpiua/django-grid-view/issues
Project-URL: Changelog, https://github.com/alpiua/django-grid-view/blob/main/CHANGELOG.md
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django<6.0,>=4.2
Provides-Extra: static-charts
Requires-Dist: matplotlib>=3.8; extra == "static-charts"
Provides-Extra: pdf
Requires-Dist: weasyprint>=62; extra == "pdf"
Requires-Dist: jinja2>=3.1; extra == "pdf"
Provides-Extra: xlsx
Requires-Dist: xlsxwriter>=3.2.0; extra == "xlsx"
Provides-Extra: xlsx-all
Requires-Dist: xlsxwriter>=3.2.0; extra == "xlsx-all"
Requires-Dist: openpyxl>=3.1; extra == "xlsx-all"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Provides-Extra: dev
Requires-Dist: basedpyright>=1.28.0; extra == "dev"
Requires-Dist: build>=1.2.0; extra == "dev"
Requires-Dist: django-stubs>=5.1.0; extra == "dev"
Requires-Dist: jinja2>=3.1; extra == "dev"
Requires-Dist: matplotlib>=3.8; extra == "dev"
Requires-Dist: matplotlib-stubs>=0.3.11; extra == "dev"
Requires-Dist: mkdocs>=1.6; extra == "dev"
Requires-Dist: mkdocs-material>=9.5; extra == "dev"
Requires-Dist: openpyxl>=3.1; extra == "dev"
Requires-Dist: pre-commit>=4.0.0; extra == "dev"
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-django>=4.8.0; extra == "dev"
Requires-Dist: ruff>=0.8.0; extra == "dev"
Requires-Dist: twine>=5.0.0; extra == "dev"
Requires-Dist: typing_extensions>=4.12.0; extra == "dev"
Requires-Dist: weasyprint>=62; extra == "dev"
Requires-Dist: xlsxwriter>=3.2.0; extra == "dev"
Dynamic: license-file

# Django Grid View

[![PyPI](https://img.shields.io/pypi/v/django-grid-view.svg?label=PyPI)](https://pypi.org/project/django-grid-view/)
[![Python](https://img.shields.io/pypi/pyversions/django-grid-view.svg)](https://pypi.org/project/django-grid-view/)
[![CI](https://github.com/alpiua/django-grid-view/actions/workflows/ci.yml/badge.svg)](https://github.com/alpiua/django-grid-view/actions/workflows/ci.yml)
[![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-2563eb)](https://alpiua.github.io/django-grid-view/)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

**Declarative grid views for Django** — server tables, AG-Grid dashboards, KPI strips, and ECharts from one typed package. You own the data (`rows` from SQL/ORM); the library owns layout, formatting, and front-end wiring.

**[Documentation](https://alpiua.github.io/django-grid-view/)** · **[LLM context bundle](https://alpiua.github.io/django-grid-view/llm/django-grid-view-llm-context.md)** · **[PyPI](https://pypi.org/project/django-grid-view/)**

---

## Why this package

Building dashboards and chat analytics in Django usually means stitching together three different stacks: hand-rolled HTML tables, AG-Grid boilerplate, and ad‑hoc chart JSON. **django-grid-view** unifies them behind a single contract:

| Principle | What it means for you |
|-----------|------------------------|
| **Structure ≠ data** | Specs (`GridViewSpec`, wire JSON) describe columns, KPIs, and charts — never row values or aggregates from an LLM. |
| **One render path** | `GridRenderer.build(spec, rows)` → `GridArtifact` → templates + `grid-view.min.js`. No parallel chart/table code paths. |
| **Typed boundaries** | `py.typed`, strict-friendly `django_grid_view.types`, JSON Schema for wire specs — host apps keep pyright/mypy honest. |
| **Production habits** | HTMX-safe AG-Grid lifecycle, saved grid preferences, uk/en i18n, optional matplotlib PNG export for PDFs. |

---

## What you get

### Simple Table

Server-rendered tables with sort, search, CSV/XLSX export, grouped headers — no SPA required.

```python
from django_grid_view.tables import Column, SimpleTableConfig

config = SimpleTableConfig(
    grid_id="products",
    columns=[Column(key="sku", label="SKU"), Column(key="name", label="Name")],
    data=rows,
)
```

```django
{% load django_grid_view %}
{% render_simple_table config %}
```

### AG-Grid helpers

Scripts, toolbar, advanced search plugins, and `GridPreference` storage for large or infinite grids. The package does **not** own your `gridApi` — you keep control of the grid instance; we supply the integration layer.

### Grid View — KPI, charts, and table together

One `GridViewSpec` drives KPI cards, ECharts blocks, and tabular layout. Ideal for dashboard pages and chat “visualizer” UIs fed by analytics SQL.

```python
from django_grid_view import GridViewSpec, RowDict, build_artifact_from_view
from django_grid_view.types import ColumnSpec, KpiSpec, KpiAggregate

artifact = build_artifact_from_view(
    {
        "grid_id": "overview",
        "columns": [{"key": "name", "label": "Name"}],
        "kpis": [{"label": "Total", "column_key": "amount", "aggregate": "sum"}],
    },
    rows,
)
```

```django
{% grid_view_bundle %}
{% render_grid_view artifact %}
```

---

## Install

```bash
pip install django-grid-view
# optional: static chart PNG export for PDF pipelines
pip install "django-grid-view[static-charts]"
```

```python
# settings.py
INSTALLED_APPS = ["django_grid_view"]
```

```python
# settings.py
DJANGO_GRID_VIEW_EXPORT_PDF_URL = "api_export_pdf"
DJANGO_GRID_VIEW_EXPORT_XLSX_URL = "api_export_xlsx"

# api/urls.py — mount under path("api/", include(...))
from django_grid_view.export.pdf_view import export_pdf
from django_grid_view.export.xlsx_view import export_xlsx
from django_grid_view.views import save_grid_settings

urlpatterns = [
    path("grid/preferences/", save_grid_settings, name="api_grid_preferences"),
    path("export/pdf/", export_pdf, name="api_export_pdf"),
    path("export/xlsx/", export_xlsx, name="api_export_xlsx"),
]
```

```bash
python manage.py migrate django_grid_view
```

Full walkthrough: **[Getting started](https://alpiua.github.io/django-grid-view/getting-started/)**.

---

## Documentation

| Topic | Link |
|-------|------|
| Simple Table | [Guide](https://alpiua.github.io/django-grid-view/simple-table/) |
| AG-Grid + HTMX | [Guide](https://alpiua.github.io/django-grid-view/ag-grid/) |
| KPI & ECharts | [Guide](https://alpiua.github.io/django-grid-view/charts-and-kpis/) |
| `GridViewSpec` → artifact | [Grid View artifacts](https://alpiua.github.io/django-grid-view/grid-view-artifacts/) |
| Python types for host apps | [Reference](https://alpiua.github.io/django-grid-view/reference/python-types/) |
| JSON Schema (wire) | `schema/grid-view-spec.v1.json` |
| Agents & coding tools | [LLM bundle](https://alpiua.github.io/django-grid-view/llm/django-grid-view-llm-context.md) · [Agent skill](https://alpiua.github.io/django-grid-view/llm/skill/) |
| Changelog | [1.0.0 notes](https://alpiua.github.io/django-grid-view/changelog/) |

---

## Roadmap — A2UI & AG-UI

**1.0 (shipped)** is the **renderer**: tables, KPI strip, ECharts, i18n, and `GridRenderer` in this repo.

Next step for host applications is protocol alignment, not replacing the renderer:

- **A2UI** — treat `GridViewSpec` as the declarative UI catalog (structure-only JSON agents and planners emit).
- **AG-UI** — stream resolved `grid_view` artifacts over an application event channel (router, SSE, chat, dashboard, or another host transport).

django-grid-view stays the single place that turns **rows + spec → `GridArtifact`**. Presenter and transport logic live in consumer apps.

---

## Development

Requires [uv](https://docs.astral.sh/uv/). CI uses `uv sync --frozen --group dev`.

Install git hooks (strips `Co-authored-by: Cursor` from commit messages):

```bash
./scripts/install-git-hooks.sh
```

```bash
uv sync --group dev
uv run pytest
uv run ruff check . && uv run ruff format --check .
uv run basedpyright --warnings src/django_grid_view tests
./scripts/docs_serve.sh   # MkDocs + LLM bundle
```

### JavaScript (maintainers only)

Browser bundles are built from TypeScript in `frontend/src/` and written to `src/django_grid_view/static/django_grid_view/` (`.js` + `.min.js`). **PyPI consumers do not need Node** — the wheel ships pre-built static files.

```
frontend/src/
  grid-view-entry.ts      # esbuild entry (IIFE bundle → grid-view.js)
  grid-view/              # modules: charts, kpi, filter-bar, search/, …
  column-settings.ts
  types/                  # chart-bind, kpi-bind (mirror Python contracts)
```

```bash
cd frontend && npm ci && npm run build   # transpile + minify
npm run typecheck && npm run lint        # strict types on search/ + contracts; eslint on all src/
npm run test:conformance                 # Python↔JS filter/search parity (shared JSON fixtures)
```

After editing `frontend/src/*.ts`, commit the regenerated static artifacts (CI verifies `git diff --exit-code src/django_grid_view/static/`).

**Load order for host pages:** `{% grid_view_bundle %}` once → `grid-view.min.js` + `column-settings.min.js`. AG-Grid pages add `scripts.html` partials. Details: [Architecture](https://alpiua.github.io/django-grid-view/architecture/#front-end-bundle) · [JavaScript API](https://alpiua.github.io/django-grid-view/reference/javascript/).

Release: tag `v*` on `main` → PyPI via trusted publishing (`environment: pypi`). Docs deploy from `main` via GitHub Actions.

---

## License

MIT — see [LICENSE](LICENSE).
