kopia lustrzana https://github.com/wagtail/wagtail
rodzic
aef6de8a2f
commit
7f6a2623d1
|
@ -51,6 +51,7 @@ Changelog
|
|||
* Add `DrilldownController` and `w-drilldown` component to support drilldown menus (Thibaud Colas)
|
||||
* Add support for `caption` on admin UI Table component (Aman Pandey)
|
||||
* Add API support for a redirects (contrib) endpoint (Rohit Sharma, Jaap Roes, Andreas Donig)
|
||||
* Add the default ability for all `SnippetViewSet` & `ModelViewSet` to support being copied (Shlomo Markowitz)
|
||||
* Fix: Update system check for overwriting storage backends to recognise the `STORAGES` setting introduced in Django 4.2 (phijma-leukeleu)
|
||||
* Fix: Prevent password change form from raising a validation error when browser autocomplete fills in the "Old password" field (Chiemezuo Akujobi)
|
||||
* Fix: Ensure that the legacy dropdown options, when closed, do not get accidentally clicked by other interactions wide viewports (CheesyPhoenix, Christer Jensen)
|
||||
|
|
|
@ -35,6 +35,7 @@ class PersonViewSet(ModelViewSet):
|
|||
form_fields = ["first_name", "last_name"]
|
||||
icon = "user"
|
||||
add_to_admin_menu = True
|
||||
copy_view_enabled = False
|
||||
inspect_view_enabled = True
|
||||
|
||||
|
||||
|
@ -94,6 +95,14 @@ You can define a `panels` or `edit_handler` attribute on the `ModelViewSet` or y
|
|||
|
||||
If neither `panels` nor `edit_handler` is defined and the {meth}`~ModelViewSet.get_edit_handler` method is not overridden, the form will be rendered as a plain Django form. You can customise the form by setting the {attr}`~ModelViewSet.form_fields` attribute to specify the fields to be shown on the form. Alternatively, you can set the {attr}`~ModelViewSet.exclude_form_fields` attribute to specify the fields to be excluded from the form. If panels are not used, you must define `form_fields` or `exclude_form_fields`, unless {meth}`~ModelViewSet.get_form_class` is overridden.
|
||||
|
||||
(modelviewset_copy)=
|
||||
|
||||
### Copy view
|
||||
|
||||
The copy view is enabled by default and will be accessible by users with the 'add' permission on the model. To disable it, set {attr}`~.ModelViewSet.copy_view_enabled` to `False`.
|
||||
|
||||
The view's form will be generated in the same way as create or edit forms. To use a custom form, override the `copy_view_class` and modify the `form_class` property on that class.
|
||||
|
||||
(modelviewset_inspect)=
|
||||
|
||||
### Inspect view
|
||||
|
|
|
@ -95,6 +95,7 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
|
|||
.. autoattribute:: export_filename
|
||||
.. autoattribute:: search_fields
|
||||
.. autoattribute:: search_backend_name
|
||||
.. autoattribute:: copy_view_enabled
|
||||
.. autoattribute:: inspect_view_enabled
|
||||
.. autoattribute:: inspect_view_fields
|
||||
.. autoattribute:: inspect_view_fields_exclude
|
||||
|
@ -104,6 +105,7 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
|
|||
.. autoattribute:: delete_view_class
|
||||
.. autoattribute:: usage_view_class
|
||||
.. autoattribute:: history_view_class
|
||||
.. autoattribute:: copy_view_class
|
||||
.. autoattribute:: inspect_view_class
|
||||
.. autoattribute:: template_prefix
|
||||
.. autoattribute:: index_template_name
|
||||
|
@ -183,6 +185,7 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
|
|||
.. autoattribute:: delete_view_class
|
||||
.. autoattribute:: usage_view_class
|
||||
.. autoattribute:: history_view_class
|
||||
.. autoattribute:: copy_view_class
|
||||
.. autoattribute:: inspect_view_class
|
||||
.. autoattribute:: revisions_view_class
|
||||
.. autoattribute:: revisions_revert_view_class
|
||||
|
|
|
@ -83,6 +83,7 @@ This feature was implemented by Nick Lee, Thibaud Colas, and Sage Abdullah.
|
|||
* Add `DrilldownController` and `w-drilldown` component to support drilldown menus (Thibaud Colas)
|
||||
* Add support for `caption` on admin UI Table component (Aman Pandey)
|
||||
* Add API support for a [redirects (contrib)](redirects_api_endpoint) endpoint (Rohit Sharma, Jaap Roes, Andreas Donig)
|
||||
* Add the default ability for all `SnippetViewSet` & `ModelViewSet` to support [being copied](modelviewset_copy), this can be disabled by `copy_view_enabled = False` (Shlomo Markowitz)
|
||||
|
||||
|
||||
### Bug fixes
|
||||
|
@ -243,6 +244,26 @@ The `use_json_field` argument to `StreamField` is no longer required, and can be
|
|||
|
||||
## Upgrade considerations - changes affecting all projects
|
||||
|
||||
### `SnippetViewSet` & `ModelViewSet` copy view enabled by default
|
||||
|
||||
The newly introduced copy view will be enabled by default for all `ModelViewSet` and `SnippetViewSet` classes.
|
||||
|
||||
This can be disabled by setting `copy_view_enabled = False`, for example.
|
||||
|
||||
```python
|
||||
class PersonViewSet(SnippetViewSet):
|
||||
model = Person
|
||||
#...
|
||||
copy_view_enabled = False
|
||||
|
||||
class PersonViewSet(ModelViewSet):
|
||||
model = Person
|
||||
#...
|
||||
copy_view_enabled = False
|
||||
```
|
||||
|
||||
See [](modelviewset_copy) for additional details about this feature.
|
||||
|
||||
## Upgrade considerations - deprecation of old functionality
|
||||
|
||||
### Removed support for Django < 4.2
|
||||
|
|
|
@ -57,6 +57,7 @@ class MemberViewSet(SnippetViewSet):
|
|||
icon = "user"
|
||||
list_display = ["name", "shirt_size", "get_shirt_size_display", UpdatedAtColumn()]
|
||||
list_per_page = 50
|
||||
copy_view_enabled = False
|
||||
inspect_view_enabled = True
|
||||
admin_url_namespace = "member_views"
|
||||
base_url_path = "internal/member"
|
||||
|
@ -92,6 +93,10 @@ You can customise the listing view to add custom columns, filters, pagination, e
|
|||
|
||||
Additionally, you can customise the base queryset for the listing view by overriding the {meth}`~SnippetViewSet.get_queryset` method.
|
||||
|
||||
## Copy view
|
||||
|
||||
The copy view is enabled by default and will be accessible by users with the 'add' permission on the model. To disable it, set {attr}`~.ModelViewSet.copy_view_enabled` to `False`. Refer to [the copy view customisations for `ModelViewSet`](modelviewset_copy) for more details.
|
||||
|
||||
## Inspect view
|
||||
|
||||
The inspect view is disabled by default, as it's not often useful for most models. To enable it, set {attr}`~.ModelViewSet.inspect_view_enabled` to `True`. Refer to [the inspect view customisations for `ModelViewSet`](modelviewset_inspect) for more details.
|
||||
|
|
|
@ -6,7 +6,7 @@ from django.contrib.admin.utils import quote
|
|||
from django.contrib.auth import get_permission_codename
|
||||
from django.contrib.auth.models import Permission
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
from django.test import RequestFactory, TestCase
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from django.utils.formats import date_format, localize
|
||||
from django.utils.html import escape
|
||||
|
@ -21,6 +21,7 @@ from wagtail.test.testapp.models import (
|
|||
SearchTestModel,
|
||||
VariousOnDeleteModel,
|
||||
)
|
||||
from wagtail.test.testapp.views import FCToyAlt1ViewSet
|
||||
from wagtail.test.utils.template_tests import AdminTemplateTestUtils
|
||||
from wagtail.test.utils.wagtail_tests import WagtailTestUtils
|
||||
from wagtail.utils.deprecation import RemovedInWagtail70Warning
|
||||
|
@ -1303,6 +1304,11 @@ class TestListingButtons(WagtailTestUtils, TestCase):
|
|||
f"Edit '{self.object}'",
|
||||
reverse("feature_complete_toy:edit", args=[quote(self.object.pk)]),
|
||||
),
|
||||
(
|
||||
"Copy",
|
||||
f"Copy '{self.object}'",
|
||||
reverse("feature_complete_toy:copy", args=[quote(self.object.pk)]),
|
||||
),
|
||||
(
|
||||
"Inspect",
|
||||
f"Inspect '{self.object}'",
|
||||
|
@ -1325,6 +1331,82 @@ class TestListingButtons(WagtailTestUtils, TestCase):
|
|||
self.assertEqual(rendered_button.attrs.get("aria-label"), aria_label)
|
||||
self.assertEqual(rendered_button.attrs.get("href"), url)
|
||||
|
||||
def test_copy_disabled(self):
|
||||
response = self.client.get(reverse("fctoy_alt1:index"))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailadmin/shared/buttons.html")
|
||||
|
||||
soup = self.get_soup(response.content)
|
||||
actions = soup.select_one("tbody tr td ul.actions")
|
||||
more_dropdown = actions.select_one("li [data-controller='w-dropdown']")
|
||||
self.assertIsNotNone(more_dropdown)
|
||||
more_button = more_dropdown.select_one("button")
|
||||
self.assertEqual(
|
||||
more_button.attrs.get("aria-label").strip(),
|
||||
f"More options for '{self.object}'",
|
||||
)
|
||||
|
||||
expected_buttons = [
|
||||
(
|
||||
"Edit",
|
||||
f"Edit '{self.object}'",
|
||||
reverse("fctoy_alt1:edit", args=[quote(self.object.pk)]),
|
||||
),
|
||||
(
|
||||
"Inspect",
|
||||
f"Inspect '{self.object}'",
|
||||
reverse("fctoy_alt1:inspect", args=[quote(self.object.pk)]),
|
||||
),
|
||||
(
|
||||
"Delete",
|
||||
f"Delete '{self.object}'",
|
||||
reverse("fctoy_alt1:delete", args=[quote(self.object.pk)]),
|
||||
),
|
||||
]
|
||||
|
||||
rendered_buttons = more_dropdown.select("a")
|
||||
self.assertEqual(len(rendered_buttons), len(expected_buttons))
|
||||
|
||||
for rendered_button, (label, aria_label, url) in zip(
|
||||
rendered_buttons, expected_buttons
|
||||
):
|
||||
self.assertEqual(rendered_button.text.strip(), label)
|
||||
self.assertEqual(rendered_button.attrs.get("aria-label"), aria_label)
|
||||
self.assertEqual(rendered_button.attrs.get("href"), url)
|
||||
|
||||
|
||||
class TestCopyView(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.user = self.login()
|
||||
self.url = reverse("feature_complete_toy:copy", args=[quote(self.object.pk)])
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cls.object = FeatureCompleteToy.objects.create(name="Test Toy")
|
||||
|
||||
def test_without_permission(self):
|
||||
self.user.is_superuser = False
|
||||
self.user.save()
|
||||
admin_permission = Permission.objects.get(
|
||||
content_type__app_label="wagtailadmin", codename="access_admin"
|
||||
)
|
||||
self.user.user_permissions.add(admin_permission)
|
||||
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
self.assertRedirects(response, reverse("wagtailadmin_home"))
|
||||
|
||||
def test_form_is_prefilled(self):
|
||||
request = RequestFactory().get(self.url)
|
||||
request.user = self.user
|
||||
view = FCToyAlt1ViewSet().copy_view_class()
|
||||
view.setup(request)
|
||||
view.model = self.object.__class__
|
||||
view.kwargs = {"pk": self.object.pk}
|
||||
|
||||
self.assertEqual(view.get_form_kwargs()["instance"], self.object)
|
||||
|
||||
|
||||
class TestEditHandler(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
|
|
|
@ -14,6 +14,7 @@ from .mixins import ( # noqa: F401
|
|||
RevisionsRevertMixin,
|
||||
)
|
||||
from .models import ( # noqa: F401
|
||||
CopyView,
|
||||
CreateView,
|
||||
DeleteView,
|
||||
EditView,
|
||||
|
|
|
@ -107,6 +107,7 @@ class IndexView(
|
|||
results_template_name = "wagtailadmin/generic/index_results.html"
|
||||
add_url_name = None
|
||||
edit_url_name = None
|
||||
copy_url_name = None
|
||||
inspect_url_name = None
|
||||
delete_url_name = None
|
||||
any_permission_required = ["add", "change", "delete"]
|
||||
|
@ -326,6 +327,10 @@ class IndexView(
|
|||
if self.edit_url_name:
|
||||
return reverse(self.edit_url_name, args=(quote(instance.pk),))
|
||||
|
||||
def get_copy_url(self, instance):
|
||||
if self.copy_url_name:
|
||||
return reverse(self.copy_url_name, args=(quote(instance.pk),))
|
||||
|
||||
def get_inspect_url(self, instance):
|
||||
if self.inspect_url_name:
|
||||
return reverse(self.inspect_url_name, args=(quote(instance.pk),))
|
||||
|
@ -422,6 +427,20 @@ class IndexView(
|
|||
priority=10,
|
||||
)
|
||||
)
|
||||
copy_url = self.get_copy_url(instance)
|
||||
can_copy = self.permission_policy.user_has_permission(self.request.user, "add")
|
||||
if copy_url and can_copy:
|
||||
buttons.append(
|
||||
ListingButton(
|
||||
_("Copy"),
|
||||
url=copy_url,
|
||||
icon_name="copy",
|
||||
attrs={
|
||||
"aria-label": _("Copy '%(title)s'") % {"title": str(instance)}
|
||||
},
|
||||
priority=20,
|
||||
)
|
||||
)
|
||||
inspect_url = self.get_inspect_url(instance)
|
||||
if inspect_url:
|
||||
buttons.append(
|
||||
|
@ -685,6 +704,14 @@ class CreateView(
|
|||
return super().form_invalid(form)
|
||||
|
||||
|
||||
class CopyView(CreateView):
|
||||
def get_object(self, queryset=None):
|
||||
return get_object_or_404(self.model, pk=self.kwargs["pk"])
|
||||
|
||||
def get_form_kwargs(self):
|
||||
return {**super().get_form_kwargs(), "instance": self.get_object()}
|
||||
|
||||
|
||||
class EditView(
|
||||
LocaleMixin,
|
||||
PanelMixin,
|
||||
|
|
|
@ -52,6 +52,9 @@ class ModelViewSet(ViewSet):
|
|||
#: The view class to use for the usage view; must be a subclass of ``wagtail.admin.views.generic.usage.UsageView``.
|
||||
usage_view_class = usage.UsageView
|
||||
|
||||
#: The view class to use for the copy view; must be a subclass of ``wagtail.admin.views.generic.CopyView``.
|
||||
copy_view_class = generic.CopyView
|
||||
|
||||
#: The view class to use for the inspect view; must be a subclass of ``wagtail.admin.views.generic.InspectView``.
|
||||
inspect_view_class = generic.InspectView
|
||||
|
||||
|
@ -88,6 +91,9 @@ class ModelViewSet(ViewSet):
|
|||
#: The fields to exclude from the inspect view.
|
||||
inspect_view_fields_exclude = []
|
||||
|
||||
#: Whether to enable the copy view. Defaults to ``True``.
|
||||
copy_view_enabled = True
|
||||
|
||||
def __init__(self, name=None, **kwargs):
|
||||
super().__init__(name=name, **kwargs)
|
||||
if not self.model:
|
||||
|
@ -129,6 +135,8 @@ class ModelViewSet(ViewSet):
|
|||
**kwargs,
|
||||
}
|
||||
)
|
||||
if self.copy_view_enabled:
|
||||
view_kwargs["copy_url_name"] = self.get_url_name("copy")
|
||||
if self.inspect_view_enabled:
|
||||
view_kwargs["inspect_url_name"] = self.get_url_name("inspect")
|
||||
return view_kwargs
|
||||
|
@ -198,6 +206,9 @@ class ModelViewSet(ViewSet):
|
|||
**kwargs,
|
||||
}
|
||||
|
||||
def get_copy_view_kwargs(self, **kwargs):
|
||||
return self.get_add_view_kwargs(**kwargs)
|
||||
|
||||
@property
|
||||
def index_view(self):
|
||||
return self.construct_view(
|
||||
|
@ -278,6 +289,10 @@ class ModelViewSet(ViewSet):
|
|||
self.inspect_view_class, **self.get_inspect_view_kwargs()
|
||||
)
|
||||
|
||||
@property
|
||||
def copy_view(self):
|
||||
return self.construct_view(self.copy_view_class, **self.get_copy_view_kwargs())
|
||||
|
||||
def get_templates(self, name="index", fallback=""):
|
||||
"""
|
||||
Utility function that provides a list of templates to try for a given
|
||||
|
@ -622,6 +637,9 @@ class ModelViewSet(ViewSet):
|
|||
path("inspect/<str:pk>/", self.inspect_view, name="inspect")
|
||||
)
|
||||
|
||||
if self.copy_view_enabled:
|
||||
urlpatterns.append(path("copy/<str:pk>/", self.copy_view, name="copy"))
|
||||
|
||||
# RemovedInWagtail70Warning: Remove legacy URL patterns
|
||||
urlpatterns += self._legacy_urlpatterns
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ from wagtail.snippets.action_menu import (
|
|||
)
|
||||
from wagtail.snippets.blocks import SnippetChooserBlock
|
||||
from wagtail.snippets.models import SNIPPET_MODELS, register_snippet
|
||||
from wagtail.snippets.views.snippets import CopyView
|
||||
from wagtail.snippets.widgets import (
|
||||
AdminSnippetChooser,
|
||||
SnippetChooserAdapter,
|
||||
|
@ -284,10 +285,10 @@ class TestSnippetListView(WagtailTestUtils, TestCase):
|
|||
)
|
||||
|
||||
def hide_delete_button_for_lovely_advert(buttons, snippet, user):
|
||||
# Edit, delete, dummy button
|
||||
self.assertEqual(len(buttons), 3)
|
||||
# Edit, delete, dummy button, copy button
|
||||
self.assertEqual(len(buttons), 4)
|
||||
buttons[:] = [button for button in buttons if button.url != delete_url]
|
||||
self.assertEqual(len(buttons), 2)
|
||||
self.assertEqual(len(buttons), 3)
|
||||
|
||||
with hooks.register_temporarily(
|
||||
"construct_snippet_listing_buttons",
|
||||
|
@ -939,6 +940,29 @@ class TestSnippetCreateView(WagtailTestUtils, TestCase):
|
|||
self.assertNotContains(response, "<em>'Save'</em>")
|
||||
|
||||
|
||||
class TestSnippetCopyView(WagtailTestUtils, TestCase):
|
||||
def setUp(self):
|
||||
self.snippet = StandardSnippet.objects.create(text="Test snippet")
|
||||
self.url = reverse(
|
||||
StandardSnippet.snippet_viewset.get_url_name("copy"),
|
||||
args=(self.snippet.pk,),
|
||||
)
|
||||
self.login()
|
||||
|
||||
def test_simple(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, "wagtailsnippets/snippets/create.html")
|
||||
|
||||
def test_form_prefilled(self):
|
||||
request = RequestFactory().get(self.url)
|
||||
view = CopyView()
|
||||
view.model = StandardSnippet
|
||||
view.setup(request, pk=self.snippet.pk)
|
||||
|
||||
self.assertEqual(view._get_initial_form_instance(), self.snippet)
|
||||
|
||||
|
||||
@override_settings(WAGTAIL_I18N_ENABLED=True)
|
||||
class TestLocaleSelectorOnCreate(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.contrib.admin.utils import quote
|
|||
from django.core import checks
|
||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||
from django.http import Http404
|
||||
from django.shortcuts import redirect
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import path, re_path, reverse, reverse_lazy
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.text import capfirst
|
||||
|
@ -35,7 +35,10 @@ from wagtail.admin.views.generic.preview import (
|
|||
)
|
||||
from wagtail.admin.viewsets import viewsets
|
||||
from wagtail.admin.viewsets.model import ModelViewSet, ModelViewSetGroup
|
||||
from wagtail.admin.widgets.button import BaseDropdownMenuButton, ButtonWithDropdown
|
||||
from wagtail.admin.widgets.button import (
|
||||
BaseDropdownMenuButton,
|
||||
ButtonWithDropdown,
|
||||
)
|
||||
from wagtail.models import (
|
||||
DraftStateMixin,
|
||||
LockableMixin,
|
||||
|
@ -277,6 +280,18 @@ class CreateView(generic.CreateEditViewOptionalFeaturesMixin, generic.CreateView
|
|||
return context
|
||||
|
||||
|
||||
class CopyView(CreateView):
|
||||
def get_object(self):
|
||||
return get_object_or_404(self.model, pk=self.kwargs["pk"])
|
||||
|
||||
def _get_initial_form_instance(self):
|
||||
instance = self.get_object()
|
||||
# Set locale of the new instance
|
||||
if self.locale:
|
||||
instance.locale = self.locale
|
||||
return instance
|
||||
|
||||
|
||||
class EditView(generic.CreateEditViewOptionalFeaturesMixin, generic.EditView):
|
||||
view_name = "edit"
|
||||
template_name = "wagtailsnippets/snippets/edit.html"
|
||||
|
@ -540,6 +555,9 @@ class SnippetViewSet(ModelViewSet):
|
|||
#: The view class to use for the create view; must be a subclass of ``wagtail.snippets.views.snippets.CreateView``.
|
||||
add_view_class = CreateView
|
||||
|
||||
#: The view class to use for the copy view; must be a subclass of ``wagtail.snippet.views.snippets.CopyView``.
|
||||
copy_view_class = CopyView
|
||||
|
||||
#: The view class to use for the edit view; must be a subclass of ``wagtail.snippets.views.snippets.EditView``.
|
||||
edit_view_class = EditView
|
||||
|
||||
|
@ -690,6 +708,9 @@ class SnippetViewSet(ModelViewSet):
|
|||
**kwargs,
|
||||
)
|
||||
|
||||
def get_copy_view_kwargs(self, **kwargs):
|
||||
return self.get_add_view_kwargs(**kwargs)
|
||||
|
||||
def get_edit_view_kwargs(self, **kwargs):
|
||||
return super().get_edit_view_kwargs(
|
||||
preview_url_name=self.get_url_name("preview_on_edit"),
|
||||
|
@ -762,6 +783,10 @@ class SnippetViewSet(ModelViewSet):
|
|||
success_url_name=self.get_url_name("edit"),
|
||||
)
|
||||
|
||||
@property
|
||||
def copy_view(self):
|
||||
return self.construct_view(self.copy_view_class, **self.get_copy_view_kwargs())
|
||||
|
||||
@property
|
||||
def unlock_view(self):
|
||||
return self.construct_view(
|
||||
|
@ -1109,6 +1134,9 @@ class SnippetViewSet(ModelViewSet):
|
|||
),
|
||||
]
|
||||
|
||||
if self.copy_view_enabled:
|
||||
urlpatterns += [path("copy/<str:pk>/", self.copy_view, name="copy")]
|
||||
|
||||
if self.inspect_view_enabled:
|
||||
urlpatterns += [
|
||||
path("inspect/<str:pk>/", self.inspect_view, name="inspect")
|
||||
|
|
|
@ -239,6 +239,7 @@ class FCToyAlt1ViewSet(ModelViewSet):
|
|||
menu_label = "FC Toys Alt 1"
|
||||
inspect_view_enabled = True
|
||||
inspect_view_fields_exclude = ["strid", "release_date"]
|
||||
copy_view_enabled = False
|
||||
|
||||
def get_index_view_kwargs(self, **kwargs):
|
||||
return super().get_index_view_kwargs(is_searchable=False, **kwargs)
|
||||
|
|
Ładowanie…
Reference in New Issue