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,