diff --git a/apps/activity/templates/activity/activity_detail.html b/apps/activity/templates/activity/activity_detail.html
index 1a8d01ee..bb0fc57a 100644
--- a/apps/activity/templates/activity/activity_detail.html
+++ b/apps/activity/templates/activity/activity_detail.html
@@ -37,6 +37,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% render_table guests %}
+
{% endif %}
{% endblock %}
diff --git a/apps/activity/views.py b/apps/activity/views.py
index 9ef0d4f2..7829a2ee 100644
--- a/apps/activity/views.py
+++ b/apps/activity/views.py
@@ -136,12 +136,19 @@ class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMix
model = Activity
context_object_name = "activity"
extra_context = {"title": _("Activity detail")}
+ export_formats = ["csv"]
tables = [
- lambda data: GuestTable(data, prefix="guests-"),
- lambda data: OpenerTable(data, prefix="opener-"),
+ GuestTable,
+ OpenerTable,
]
+ def get_tables(self):
+ tables = super().get_tables()
+ tables[0].prefix = "guests"
+ tables[1].prefix = "opener"
+ return tables
+
def get_tables_data(self):
return [
Guest.objects.filter(activity=self.object)
@@ -150,6 +157,51 @@ class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMix
.filter(PermissionBackend.filter_queryset(self.request, Opener, "view")),
]
+ def render_to_response(self, context, **response_kwargs):
+ """
+ Gère l'export CSV manuel pour MultiTableMixin.
+ """
+ if "_export" in self.request.GET:
+ import tablib
+ table_name = self.request.GET.get("table")
+ if table_name:
+ tables = self.get_tables()
+ data_list = self.get_tables_data()
+
+ for t, d in zip(tables, data_list):
+ if t.prefix == table_name:
+ # Préparer le CSV
+ dataset = tablib.Dataset()
+ columns = list(t.base_columns) # noms des colonnes
+ dataset.headers = columns
+
+ for row in d:
+ values = []
+ for col in columns:
+ try:
+ val = getattr(row, col, "")
+ # Gestion spéciale pour la colonne 'entry'
+ if col == "entry":
+ if getattr(row, "has_entry", False):
+ val = timezone.localtime(row.entry.time).strftime("%Y-%m-%d %H:%M:%S")
+ else:
+ val = ""
+ values.append(str(val) if val is not None else "")
+ except Exception: # RelatedObjectDoesNotExist ou autre
+ values.append("")
+ dataset.append(values)
+
+ csv_bytes = dataset.export("csv")
+ if isinstance(csv_bytes, str):
+ csv_bytes = csv_bytes.encode("utf-8")
+
+ response = HttpResponse(csv_bytes, content_type="text/csv")
+ response["Content-Disposition"] = f'attachment; filename="{table_name}.csv"'
+ return response
+
+ # Sinon rendu normal
+ return super().render_to_response(context, **response_kwargs)
+
def get_context_data(self, **kwargs):
context = super().get_context_data()
diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json
index 7946e66d..58bfd264 100644
--- a/apps/permission/fixtures/initial.json
+++ b/apps/permission/fixtures/initial.json
@@ -5201,6 +5201,7 @@
"permissions": [
37,
41,
+ 42,
53,
54,
55,