diff --git a/docs/reference/contrib/modeladmin/indexview.rst b/docs/reference/contrib/modeladmin/indexview.rst index 1aeb0338e3..15d4d8c40c 100644 --- a/docs/reference/contrib/modeladmin/indexview.rst +++ b/docs/reference/contrib/modeladmin/indexview.rst @@ -293,6 +293,21 @@ for your model. For example: list_filter = ('is_staff', 'company') +.. _modeladmin_export_filename: + +------------------------------ +``ModelAdmin.export_filename`` +------------------------------ + +**Expected value**: A string specifying the filename of an exported spreadsheet, +without file extensions. + +.. code-block:: python + + class PersonAdmin(ModelAdmin): + export_filename = 'people_spreadsheet' + + .. _modeladmin_search_fields: ---------------------------- diff --git a/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py b/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py index 65e92c911b..39fe558f65 100644 --- a/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py +++ b/wagtail/contrib/modeladmin/tests/test_simple_modeladmin.py @@ -48,8 +48,11 @@ class TestBookIndexView(TestCase, WagtailTestUtils): # Export the whole queryset response = self.get(export='csv') - # Check response - all books should be in it self.assertEqual(response.status_code, 200) + # Check attachment is present and named correctly using the modeladmin export_filename + self.assertEqual(response.get('content-disposition'), 'attachment; filename="books-export.csv"') + + # Check response - all books should be in it data_lines = response.getvalue().decode().split("\n") self.assertEqual(data_lines[0], 'Title,Author\r') self.assertEqual(data_lines[1], 'Charlie and the Chocolate Factory,Roald Dahl\r') @@ -61,8 +64,11 @@ class TestBookIndexView(TestCase, WagtailTestUtils): # Export the whole queryset response = self.get(export='xlsx') - # Check response - all books should be in it self.assertEqual(response.status_code, 200) + # Check attachment is present and named correctly using the modeladmin export_filename + self.assertEqual(response.get('content-disposition'), 'attachment; filename="books-export.xlsx"') + + # Check response - all books should be in it workbook_data = response.getvalue() worksheet = load_workbook(filename=BytesIO(workbook_data))['Sheet1'] cell_array = [[cell.value for cell in row] for row in worksheet.rows] diff --git a/wagtail/contrib/modeladmin/views.py b/wagtail/contrib/modeladmin/views.py index 64e2e6be94..a7d563921c 100644 --- a/wagtail/contrib/modeladmin/views.py +++ b/wagtail/contrib/modeladmin/views.py @@ -265,6 +265,10 @@ class IndexView(SpreadsheetExportMixin, WMABaseView): return super().dispatch(request, *args, **kwargs) + def get_filename(self): + """ Get filename for exported spreadsheet, without extension """ + return getattr(self.model_admin, 'export_filename', super().get_filename()) + def get_heading(self, queryset, field): """ Get headings for exported spreadsheet column for the relevant field """ heading_override = self.export_headings.get(field) diff --git a/wagtail/tests/modeladmintest/wagtail_hooks.py b/wagtail/tests/modeladmintest/wagtail_hooks.py index 503acbdd97..8059c7878d 100644 --- a/wagtail/tests/modeladmintest/wagtail_hooks.py +++ b/wagtail/tests/modeladmintest/wagtail_hooks.py @@ -48,6 +48,7 @@ class BookModelAdmin(ThumbnailMixin, ModelAdmin): list_display = ('title', 'author', 'admin_thumb') list_export = ('title', 'author') list_filter = ('author', ) + export_filename = "books-export" ordering = ('title', ) inspect_view_enabled = True inspect_view_fields_exclude = ('title', )