Export a table whole, as a themed PDF or a CSV of the same rows (#341) #1088

Merged
tiagoagueda merged 1 commit from 341-list-export into main 2026-10-31 04:43:15 +00:00
Owner

Postulo could not export a list: printing one was the browser's dialog over
one page of rows, and the templates plugin had nothing for a list template
to set.

Applications, Companies and Listings each have Export beside Columns and
Views. It opens /tables//export/, which says what the export will
hold (the row count, the person's columns in their order, the filters and
the sort in words, and the row ceiling) and offers a theme, a language and
a paper. Download PDF and Download CSV post to /tables//export/file
with the table's question in the address; a GET there draws the same file
and remembers nothing. Both are downloads and are never filed (#236).

The rows are the page's own: each table names its list view (rows_from),
whose table_rows() is the queryset the page paginates, unpaginated, so the
scoping, the view's own filters (tab, group, status, whose) and the table's
are applied exactly as on the page. Applications export the table's shape
even where the board was chosen. Each table writes its cells as text
(Table.text), dates in the reader's format and zone, inside the document's
language.

One theme kind for every list, ThemeKind.LIST, with plain and classic
templates extending documents/themes/base_list.html. A list theme is handed
plain values by list_export.as_context: list, title, person, produced_at,
filters, sort, columns, rows, count, total, limit, truncated and left_out,
plus the usual document names and the paper. The theme is remembered per
person in Profile.document_themes as the report's is (#340), on a POST only.
With nothing chosen the paper is the person's default turned landscape,
where the theme prints on that (#344). A PDF holds at most 1,000 rows and a
CSV 10,000, said on the page and in the document. The CSV goes through
spreadsheets.row (#218).

No migration and no archive format change: the remembered list theme lives
in the existing document_themes column, whose import already takes any
ThemeKind.

Closes #341

Notes for review

  • Export: Applications, Companies and Listings each get an Export button.
    • It opens a page saying what the file will hold: the row count, the person's columns, filters and sort in words, and the ceiling.
    • It offers a theme, a language and a paper.
    • The download is a themed PDF or a CSV of the same rows as the page, through each list view's own queryset. It is never filed.
  • The theme: ThemeKind.LIST, one kind for every list, with plain values from list_export.as_context. It is remembered in Profile.document_themes.
  • Decisions the issue left open:
    • Drawn in the request, not in the background, because a download needs no file store. The caps are 1,000 rows for a PDF and 10,000 for a CSV; the page states both, and the PDF says how many rows it left out.
    • With no paper chosen, the person's default turned landscape, where the theme prints on it.
    • Applications always export the table, settled rows included, even when the person uses the board.
    • Listings export the tab they're on.
    • Empty cells: empty in the CSV, a dash in the PDF.
  • CSV: every cell goes through spreadsheets.row (#218).
  • No migration and no format bump.
  • WeasyPrint: the list case of the every-theme × kind × paper render test runs only in CI.

🤖 Generated with Claude Code

Postulo could not export a list: printing one was the browser's dialog over one page of rows, and the templates plugin had nothing for a list template to set. Applications, Companies and Listings each have Export beside Columns and Views. It opens /tables/<name>/export/, which says what the export will hold (the row count, the person's columns in their order, the filters and the sort in words, and the row ceiling) and offers a theme, a language and a paper. Download PDF and Download CSV post to /tables/<name>/export/file with the table's question in the address; a GET there draws the same file and remembers nothing. Both are downloads and are never filed (#236). The rows are the page's own: each table names its list view (rows_from), whose table_rows() is the queryset the page paginates, unpaginated, so the scoping, the view's own filters (tab, group, status, whose) and the table's are applied exactly as on the page. Applications export the table's shape even where the board was chosen. Each table writes its cells as text (Table.text), dates in the reader's format and zone, inside the document's language. One theme kind for every list, ThemeKind.LIST, with plain and classic templates extending documents/themes/base_list.html. A list theme is handed plain values by list_export.as_context: list, title, person, produced_at, filters, sort, columns, rows, count, total, limit, truncated and left_out, plus the usual document names and the paper. The theme is remembered per person in Profile.document_themes as the report's is (#340), on a POST only. With nothing chosen the paper is the person's default turned landscape, where the theme prints on that (#344). A PDF holds at most 1,000 rows and a CSV 10,000, said on the page and in the document. The CSV goes through spreadsheets.row (#218). No migration and no archive format change: the remembered list theme lives in the existing document_themes column, whose import already takes any ThemeKind. Closes #341 ## Notes for review - **Export:** Applications, Companies and Listings each get an *Export* button. - It opens a page saying what the file will hold: the row count, the person's columns, filters and sort in words, and the ceiling. - It offers a theme, a language and a paper. - The download is a themed PDF or a CSV of the same rows as the page, through each list view's own queryset. It is never filed. - **The theme:** `ThemeKind.LIST`, one kind for every list, with plain values from `list_export.as_context`. It is remembered in `Profile.document_themes`. - **Decisions the issue left open:** - Drawn in the request, not in the background, because a download needs no file store. The caps are 1,000 rows for a PDF and 10,000 for a CSV; the page states both, and the PDF says how many rows it left out. - With no paper chosen, the person's default turned landscape, where the theme prints on it. - Applications always export the table, settled rows included, even when the person uses the board. - Listings export the tab they're on. - Empty cells: empty in the CSV, a dash in the PDF. - **CSV:** every cell goes through `spreadsheets.row` (#218). - **No migration and no format bump.** - **WeasyPrint:** the list case of the every-theme × kind × paper render test runs only in CI. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Export a table whole, as a themed PDF or a CSV of the same rows (#341)
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Failing after 16m37s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m56s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m52s
CI / Security audit (pull_request) Successful in 1m21s
CI / Browser tests (Chromium) (pull_request) Has been cancelled
e7e311bcee
Postulo could not export a list: printing one was the browser's dialog over
one page of rows, and the templates plugin had nothing for a list template
to set.

Applications, Companies and Listings each have Export beside Columns and
Views. It opens /tables/<name>/export/, which says what the export will
hold (the row count, the person's columns in their order, the filters and
the sort in words, and the row ceiling) and offers a theme, a language and
a paper. Download PDF and Download CSV post to /tables/<name>/export/file
with the table's question in the address; a GET there draws the same file
and remembers nothing. Both are downloads and are never filed (#236).

The rows are the page's own: each table names its list view (rows_from),
whose table_rows() is the queryset the page paginates, unpaginated, so the
scoping, the view's own filters (tab, group, status, whose) and the table's
are applied exactly as on the page. Applications export the table's shape
even where the board was chosen. Each table writes its cells as text
(Table.text), dates in the reader's format and zone, inside the document's
language.

One theme kind for every list, ThemeKind.LIST, with plain and classic
templates extending documents/themes/base_list.html. A list theme is handed
plain values by list_export.as_context: list, title, person, produced_at,
filters, sort, columns, rows, count, total, limit, truncated and left_out,
plus the usual document names and the paper. The theme is remembered per
person in Profile.document_themes as the report's is (#340), on a POST only.
With nothing chosen the paper is the person's default turned landscape,
where the theme prints on that (#344). A PDF holds at most 1,000 rows and a
CSV 10,000, said on the page and in the document. The CSV goes through
spreadsheets.row (#218).

No migration and no archive format change: the remembered list theme lives
in the existing document_themes column, whose import already takes any
ThemeKind.

Closes #341

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tiagoagueda force-pushed 341-list-export from e7e311bcee
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Failing after 16m37s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m56s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m52s
CI / Security audit (pull_request) Successful in 1m21s
CI / Browser tests (Chromium) (pull_request) Has been cancelled
to c8e9efa289
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 14m52s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m24s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m37s
CI / Security audit (pull_request) Successful in 1m18s
CI / Browser tests (Chromium) (pull_request) Failing after 38m10s
2026-10-30 22:23:45 +00:00
Compare
tiagoagueda force-pushed 341-list-export from c8e9efa289
Some checks failed
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 14m52s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 3m24s
CI / Database tests on PostgreSQL (pull_request) Successful in 4m37s
CI / Security audit (pull_request) Successful in 1m18s
CI / Browser tests (Chromium) (pull_request) Failing after 38m10s
to 16fec41e0a
All checks were successful
CI / Unit tests and coverage (Python 3.14) (pull_request) Successful in 15m43s
CI / Checks: lint, migrations, catalogues, settings, built files (pull_request) Successful in 1m39s
CI / Database tests on PostgreSQL (pull_request) Successful in 3m45s
CI / Security audit (pull_request) Successful in 1m4s
CI / Browser tests (Chromium) (pull_request) Successful in 35m47s
2026-10-31 02:21:31 +00:00
Compare
tiagoagueda deleted branch 341-list-export 2026-10-31 04:43:17 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo!1088
No description provided.