From 8e6e37121e5e58a9751ac15dea2ff8e8feb68203 Mon Sep 17 00:00:00 2001 From: Tom Wiesing Date: Tue, 19 Sep 2023 15:22:32 +0200 Subject: [PATCH] Add export for donations --- alumni/admin/actions.py | 26 +++++++++++++++++++------- donations/admin.py | 6 +++++- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/alumni/admin/actions.py b/alumni/admin/actions.py index 8479104..3e97e85 100644 --- a/alumni/admin/actions.py +++ b/alumni/admin/actions.py @@ -15,7 +15,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from typing import Any, List, Iterator, Optional, Callable + from typing import Any, List, Iterator, Optional, Callable, Tuple from django.contrib.admin import ModelAdmin from django.http import HttpRequest from django.db.models import QuerySet @@ -94,6 +94,7 @@ def to_excel(value: Any) -> ExcelCellType: def export_as_xslx_action( description: str = "Export selected objects as XSLX file", fields: Optional[Iterator[str]] = None, + extra_fields: Optional[Iterator[Tuple[str, Callable]]] = None, header: bool = True, ) -> Callable[[ModelAdmin, HttpRequest, QuerySet], HttpResponse]: """ @@ -111,6 +112,12 @@ def export_as_xslx( else: field_names = fields + # get the extra names + if not extra_fields: + extra_names = [] + else: + extra_names = [n for (n, _) in extra_fields] + # Create a response header response = HttpResponse( content_type="application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" @@ -126,24 +133,29 @@ def export_as_xslx( # Write the header (if desired) if header: - def makeHeaderCell(field): c = cell.Cell(ws, value=field) c.font = styles.Font(bold=True) return c - ws.append([makeHeaderCell(field) for field in field_names]) + ws.append([makeHeaderCell(field) for field in field_names] + extra_names) # Write each of the rows - for row in queryset.values_list(*field_names): - + copy = queryset.all() + for (raw, row) in zip(copy, queryset.values_list(*field_names)): def makeCell(prop): try: return to_excel(prop) except: return str(prop) - - ws.append([makeCell(c) for c in row]) + + cells = [makeCell(c) for c in row] + if extra_fields: + extra_cells = [makeCell(f(raw)) for (_, f) in extra_fields] + else: + extra_cells = [] + + ws.append(cells+extra_cells) # adjust column widths # adapted from https://stackoverflow.com/a/39530676 diff --git a/donations/admin.py b/donations/admin.py index cc2aeea..3d93c90 100644 --- a/donations/admin.py +++ b/donations/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin from donations.models import DonationTarget, Donation - +from alumni.admin.actions import export_as_xslx_action def deactivate(modeladmin, request, queryset): queryset.update(active=False) @@ -15,6 +15,10 @@ class DonationAdmin(admin.ModelAdmin): list_filter = ("target", "completed") date_hierarchy = "completed" + actions = [ + export_as_xslx_action("Export as XSLX", fields=["completed", "target"], extra_fields=[("amount", lambda x:x.amount)]), + ] + class DonationTargetAdmin(admin.ModelAdmin): list_display = ("label", "active")