Add docs and tests for exporting snippets listing

pull/10626/head
Sage Abdullah 2023-07-03 15:18:02 +01:00
rodzic 0a731b37f4
commit 428b7914e2
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: EB1A33CC51CC0217
5 zmienionych plików z 102 dodań i 0 usunięć

Wyświetl plik

@ -87,6 +87,7 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: menu_name .. autoattribute:: menu_name
.. autoattribute:: menu_order .. autoattribute:: menu_order
.. autoattribute:: list_display .. autoattribute:: list_display
.. autoattribute:: list_export
.. autoattribute:: list_filter .. autoattribute:: list_filter
.. autoattribute:: filterset_class .. autoattribute:: filterset_class
.. autoattribute:: search_fields .. autoattribute:: search_fields

Wyświetl plik

@ -93,6 +93,12 @@ You can add the ability to filter the listing view by defining a {attr}`~wagtail
If you would like to make further customisations to the filtering mechanism, you can also use a custom `wagtail.admin.filters.WagtailFilterSet` subclass by overriding the {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.filterset_class` attribute. The `list_filter` attribute is ignored if `filterset_class` is set. For more details, refer to [django-filter's documentation](https://django-filter.readthedocs.io/en/stable/guide/usage.html#the-filter). If you would like to make further customisations to the filtering mechanism, you can also use a custom `wagtail.admin.filters.WagtailFilterSet` subclass by overriding the {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.filterset_class` attribute. The `list_filter` attribute is ignored if `filterset_class` is set. For more details, refer to [django-filter's documentation](https://django-filter.readthedocs.io/en/stable/guide/usage.html#the-filter).
You can add the ability to export the listing view to a spreadsheet by setting the {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.list_export` attribute to specify the columns to be exported.
```{versionadded} 5.1
The ability to export the listing view was added.
```
## Templates ## Templates
For all views that are used for a snippet model, Wagtail looks for templates in the following directories within your project or app, before resorting to the defaults: For all views that are used for a snippet model, Wagtail looks for templates in the following directories within your project or app, before resorting to the defaults:

Wyświetl plik

@ -1,5 +1,8 @@
from datetime import datetime
from io import BytesIO
from unittest import mock from unittest import mock
from django.conf import settings
from django.contrib.admin.utils import quote from django.contrib.admin.utils import quote
from django.contrib.auth import get_permission_codename from django.contrib.auth import get_permission_codename
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
@ -8,11 +11,13 @@ from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase, TransactionTestCase from django.test import TestCase, TransactionTestCase
from django.urls import reverse from django.urls import reverse
from django.utils.timezone import now from django.utils.timezone import now
from openpyxl import load_workbook
from wagtail.admin.admin_url_finder import AdminURLFinder from wagtail.admin.admin_url_finder import AdminURLFinder
from wagtail.admin.menu import admin_menu, settings_menu from wagtail.admin.menu import admin_menu, settings_menu
from wagtail.admin.panels import get_edit_handler from wagtail.admin.panels import get_edit_handler
from wagtail.admin.staticfiles import versioned_static from wagtail.admin.staticfiles import versioned_static
from wagtail.admin.views.mixins import ExcelDateFormatter
from wagtail.blocks.field_block import FieldBlockAdapter from wagtail.blocks.field_block import FieldBlockAdapter
from wagtail.coreutils import get_dummy_request from wagtail.coreutils import get_dummy_request
from wagtail.models import Locale, Workflow, WorkflowContentType from wagtail.models import Locale, Workflow, WorkflowContentType
@ -670,6 +675,88 @@ class TestListViewWithCustomColumns(BaseSnippetViewSetTests):
self.assertTagInHTML("<th>", html, count=5, allow_extra_attrs=True) self.assertTagInHTML("<th>", html, count=5, allow_extra_attrs=True)
class TestListExport(BaseSnippetViewSetTests):
model = FullFeaturedSnippet
@classmethod
def setUpTestData(cls):
cls.model.objects.create(text="Pot Noodle", country_code="UK")
cls.some_date = now().date()
cls.first_published_at = "2023-07-01T13:12:11.100"
if settings.USE_TZ:
cls.first_published_at = "2023-07-01T13:12:11.100Z"
obj = cls.model.objects.create(
text="Indomie",
country_code="ID",
first_published_at=cls.first_published_at,
)
# Refresh so the first_published_at becomes a datetime object
obj.refresh_from_db()
cls.first_published_at = obj.first_published_at
def test_get_not_export_shows_export_buttons(self):
response = self.client.get(self.get_url("list"))
self.assertContains(response, "Download CSV")
self.assertContains(response, self.get_url("list") + "?export=csv")
self.assertContains(response, "Download XLSX")
self.assertContains(response, self.get_url("list") + "?export=xlsx")
def test_csv_export(self):
response = self.client.get(self.get_url("list"), {"export": "csv"})
self.assertEqual(response.status_code, 200)
data_lines = response.getvalue().decode().split("\n")
self.assertEqual(
data_lines[0],
"Text,Country Code,get_foo_country_code,Some Date,First Published At\r",
)
self.assertEqual(
data_lines[1],
f"Indomie,ID,Foo ID,{self.some_date.isoformat()},{self.first_published_at.isoformat(sep=' ')}\r",
)
self.assertEqual(
data_lines[2],
f"Pot Noodle,UK,Foo UK,{self.some_date.isoformat()},None\r",
)
def test_xlsx_export(self):
response = self.client.get(self.get_url("list"), {"export": "xlsx"})
self.assertEqual(response.status_code, 200)
workbook_data = response.getvalue()
worksheet = load_workbook(filename=BytesIO(workbook_data)).active
cell_array = [[cell.value for cell in row] for row in worksheet.rows]
self.assertEqual(
cell_array[0],
[
"Text",
"Country Code",
"get_foo_country_code",
"Some Date",
"First Published At",
],
)
self.assertEqual(
cell_array[1],
[
"Indomie",
"ID",
"Foo ID",
self.some_date,
datetime(2023, 7, 1, 13, 12, 11, 100000),
],
)
self.assertEqual(
cell_array[2],
["Pot Noodle", "UK", "Foo UK", self.some_date, "None"],
)
self.assertEqual(len(cell_array), 3)
self.assertEqual(worksheet["E2"].number_format, ExcelDateFormatter().get())
class TestCustomTemplates(BaseSnippetViewSetTests): class TestCustomTemplates(BaseSnippetViewSetTests):
model = FullFeaturedSnippet model = FullFeaturedSnippet

Wyświetl plik

@ -669,6 +669,7 @@ class SnippetViewSet(ModelViewSet):
#: If ``filterset_class`` is set, this attribute will be ignored. #: If ``filterset_class`` is set, this attribute will be ignored.
list_filter = None list_filter = None
#: A list or tuple, where each item is the name of a field, an attribute, or a single-argument callable on the model.
list_export = [] list_export = []
#: The number of items to display per page in the index view. Defaults to 20. #: The number of items to display per page in the index view. Defaults to 20.

Wyświetl plik

@ -257,6 +257,13 @@ class FullFeaturedSnippetViewSet(SnippetViewSet):
chooser_per_page = 15 chooser_per_page = 15
filterset_class = FullFeaturedSnippetFilterSet filterset_class = FullFeaturedSnippetFilterSet
list_display = ["text", "country_code", "get_foo_country_code", UpdatedAtColumn()] list_display = ["text", "country_code", "get_foo_country_code", UpdatedAtColumn()]
list_export = [
"text",
"country_code",
"get_foo_country_code",
"some_date",
"first_published_at",
]
index_template_name = "tests/fullfeaturedsnippet_index.html" index_template_name = "tests/fullfeaturedsnippet_index.html"
ordering = ["text", "-_updated_at", "-pk"] ordering = ["text", "-_updated_at", "-pk"]
add_to_admin_menu = True add_to_admin_menu = True