kopia lustrzana https://github.com/wagtail/wagtail
Move SnippetViewSet.list_filter and filterset_class definition to ModelViewSet
rodzic
2b6a580637
commit
1fa124fe82
|
@ -81,6 +81,8 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
|
|||
|
||||
.. autoattribute:: add_to_reference_index
|
||||
.. autoattribute:: list_display
|
||||
.. autoattribute:: list_filter
|
||||
.. autoattribute:: filterset_class
|
||||
.. autoattribute:: index_view_class
|
||||
.. autoattribute:: add_view_class
|
||||
.. autoattribute:: edit_view_class
|
||||
|
@ -147,8 +149,6 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
|
|||
|
||||
.. autoattribute:: model
|
||||
.. autoattribute:: list_export
|
||||
.. autoattribute:: list_filter
|
||||
.. autoattribute:: filterset_class
|
||||
.. autoattribute:: search_fields
|
||||
.. autoattribute:: search_backend_name
|
||||
.. autoattribute:: list_per_page
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import datetime
|
||||
|
||||
from django.contrib.admin.utils import quote
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
@ -152,3 +154,106 @@ class TestCustomColumns(WagtailTestUtils, TestCase):
|
|||
updated_at = soup.select("th a")[-1]
|
||||
self.assertEqual(updated_at.text.strip(), "Updated")
|
||||
self.assertEqual(updated_at["href"], f"{index_url}?ordering=_updated_at")
|
||||
|
||||
|
||||
class TestListFilter(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.user = self.login()
|
||||
|
||||
def get(self, params=None):
|
||||
return self.client.get(reverse("feature_complete_toy:index"), params)
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
FeatureCompleteToy.objects.create(
|
||||
name="Buzz Lightyear",
|
||||
release_date=datetime.date(1995, 11, 19),
|
||||
)
|
||||
FeatureCompleteToy.objects.create(
|
||||
name="Forky",
|
||||
release_date=datetime.date(2019, 6, 11),
|
||||
)
|
||||
|
||||
def test_unfiltered_no_results(self):
|
||||
FeatureCompleteToy.objects.all().delete()
|
||||
response = self.get()
|
||||
self.assertContains(response, "There are no feature complete toys to display")
|
||||
self.assertContains(
|
||||
response,
|
||||
'<label class="w-field__label" for="id_release_date" id="id_release_date-label">Release date</label>',
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<input type="text" name="release_date" autocomplete="off" id="id_release_date">',
|
||||
html=True,
|
||||
)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html")
|
||||
|
||||
def test_unfiltered_with_results(self):
|
||||
response = self.get()
|
||||
self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html")
|
||||
self.assertContains(response, "Buzz Lightyear")
|
||||
self.assertContains(response, "Forky")
|
||||
self.assertNotContains(response, "There are 2 matches")
|
||||
self.assertContains(
|
||||
response,
|
||||
'<label class="w-field__label" for="id_release_date" id="id_release_date-label">Release date</label>',
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<input type="text" name="release_date" autocomplete="off" id="id_release_date">',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_empty_filter_with_results(self):
|
||||
response = self.get({"release_date": ""})
|
||||
self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html")
|
||||
self.assertContains(response, "Buzz Lightyear")
|
||||
self.assertContains(response, "Forky")
|
||||
self.assertNotContains(response, "There are 2 matches")
|
||||
self.assertContains(
|
||||
response,
|
||||
'<label class="w-field__label" for="id_release_date" id="id_release_date-label">Release date</label>',
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<input type="text" name="release_date" value="" autocomplete="off" id="id_release_date">',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_filtered_no_results(self):
|
||||
response = self.get({"release_date": "1970-01-01"})
|
||||
self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html")
|
||||
self.assertContains(
|
||||
response,
|
||||
"No feature complete toys match your query",
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<label class="w-field__label" for="id_release_date" id="id_release_date-label">Release date</label>',
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<input type="text" name="release_date" value="1970-01-01" autocomplete="off" id="id_release_date">',
|
||||
html=True,
|
||||
)
|
||||
|
||||
def test_filtered_with_results(self):
|
||||
response = self.get({"release_date": "1995-11-19"})
|
||||
self.assertTemplateUsed(response, "wagtailadmin/shared/filters.html")
|
||||
self.assertContains(response, "Buzz Lightyear")
|
||||
self.assertContains(response, "There is 1 match")
|
||||
self.assertContains(
|
||||
response,
|
||||
'<label class="w-field__label" for="id_release_date" id="id_release_date-label">Release date</label>',
|
||||
html=True,
|
||||
)
|
||||
self.assertContains(
|
||||
response,
|
||||
'<input type="text" name="release_date" value="1995-11-19" autocomplete="off" id="id_release_date">',
|
||||
html=True,
|
||||
)
|
||||
|
|
|
@ -77,6 +77,8 @@ class ModelViewSet(ViewSet):
|
|||
"edit_url_name": self.get_url_name("edit"),
|
||||
"header_icon": self.icon,
|
||||
"list_display": self.list_display,
|
||||
"list_filter": self.list_filter,
|
||||
"filterset_class": self.filterset_class,
|
||||
**kwargs,
|
||||
}
|
||||
|
||||
|
@ -266,6 +268,31 @@ class ModelViewSet(ViewSet):
|
|||
"""
|
||||
return self.index_view_class.list_display
|
||||
|
||||
@cached_property
|
||||
def list_filter(self):
|
||||
"""
|
||||
A list or tuple, where each item is the name of model fields of type
|
||||
``BooleanField``, ``CharField``, ``DateField``, ``DateTimeField``,
|
||||
``IntegerField`` or ``ForeignKey``.
|
||||
Alternatively, it can also be a dictionary that maps a field name to a
|
||||
list of lookup expressions.
|
||||
This will be passed as django-filter's ``FilterSet.Meta.fields``
|
||||
attribute. See
|
||||
`its documentation <https://django-filter.readthedocs.io/en/stable/guide/usage.html#generating-filters-with-meta-fields>`_
|
||||
for more details.
|
||||
If ``filterset_class`` is set, this attribute will be ignored.
|
||||
"""
|
||||
return self.index_view_class.list_filter
|
||||
|
||||
@cached_property
|
||||
def filterset_class(self):
|
||||
"""
|
||||
A subclass of ``wagtail.admin.filters.WagtailFilterSet``, which is a
|
||||
subclass of `django_filters.FilterSet <https://django-filter.readthedocs.io/en/stable/ref/filterset.html>`_.
|
||||
This will be passed to the ``filterset_class`` attribute of the index view.
|
||||
"""
|
||||
return self.index_view_class.filterset_class
|
||||
|
||||
@cached_property
|
||||
def menu_label(self):
|
||||
return self.model_opts.verbose_name_plural.title()
|
||||
|
|
|
@ -621,15 +621,6 @@ class SnippetViewSet(ModelViewSet):
|
|||
#: The model class to be registered as a snippet with this viewset.
|
||||
model = None
|
||||
|
||||
#: A subclass of ``wagtail.admin.filters.WagtailFilterSet``, which is a subclass of `django_filters.FilterSet <https://django-filter.readthedocs.io/en/stable/ref/filterset.html>`_. This will be passed to the ``filterset_class`` attribute of the index view.
|
||||
filterset_class = None
|
||||
|
||||
#: A list or tuple, where each item is the name of model fields of type ``BooleanField``, ``CharField``, ``DateField``, ``DateTimeField``, ``IntegerField`` or ``ForeignKey``.
|
||||
#: Alternatively, it can also be a dictionary that maps a field name to a list of lookup expressions.
|
||||
#: This will be passed as django-filter's ``FilterSet.Meta.fields`` attribute. See `its documentation <https://django-filter.readthedocs.io/en/stable/guide/usage.html#generating-filters-with-meta-fields>`_ for more details.
|
||||
#: If ``filterset_class`` is set, this attribute will be ignored.
|
||||
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 = []
|
||||
|
||||
|
@ -824,11 +815,9 @@ class SnippetViewSet(ModelViewSet):
|
|||
def get_index_view_kwargs(self, **kwargs):
|
||||
return super().get_index_view_kwargs(
|
||||
queryset=self.get_queryset,
|
||||
filterset_class=self.filterset_class,
|
||||
index_url_name=self.get_url_name("list"),
|
||||
index_results_url_name=self.get_url_name("list_results"),
|
||||
delete_url_name=self.get_url_name("delete"),
|
||||
list_filter=self.list_filter,
|
||||
list_export=self.list_export,
|
||||
export_filename=self.get_export_filename(),
|
||||
paginate_by=self.list_per_page,
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.2.4 on 2023-08-21 10:56
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("tests", "0026_featurecompletetoy"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="featurecompletetoy",
|
||||
name="release_date",
|
||||
field=models.DateField(default=datetime.date.today),
|
||||
),
|
||||
]
|
|
@ -1,3 +1,4 @@
|
|||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import uuid
|
||||
|
@ -2140,6 +2141,7 @@ class GenericSnippetNoFieldIndexPage(GenericSnippetPage):
|
|||
# Models to be registered with a ModelViewSet
|
||||
class FeatureCompleteToy(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
release_date = models.DateField(default=datetime.date.today)
|
||||
|
||||
def is_cool(self):
|
||||
if self.name == self.name[::-1]:
|
||||
|
|
|
@ -205,3 +205,4 @@ class FeatureCompleteToyViewSet(ModelViewSet):
|
|||
template_prefix = "customprefix/"
|
||||
index_template_name = "tests/fctoy_index.html"
|
||||
list_display = ["name", BooleanColumn("is_cool"), UpdatedAtColumn()]
|
||||
list_filter = ["name", "release_date"]
|
||||
|
|
Ładowanie…
Reference in New Issue