Add docs and tests for Snippets template overrides

pull/10303/head
Sage Abdullah 2023-03-27 14:52:04 +01:00 zatwierdzone przez Matt Westcott
rodzic 1638695d12
commit f2ab3ae774
12 zmienionych plików z 165 dodań i 2 usunięć

Wyświetl plik

@ -104,6 +104,18 @@ Viewsets are Wagtail's mechanism for defining a group of related admin views wit
.. autoattribute:: lock_view_class
.. autoattribute:: unlock_view_class
.. autoattribute:: chooser_viewset_class
.. autoattribute:: index_template_name
.. autoattribute:: index_results_template_name
.. autoattribute:: create_template_name
.. autoattribute:: edit_template_name
.. autoattribute:: delete_template_name
.. autoattribute:: history_template_name
.. automethod:: get_index_template
.. automethod:: get_index_results_template
.. automethod:: get_create_template
.. automethod:: get_edit_template
.. automethod:: get_delete_template
.. automethod:: get_history_template
.. automethod:: get_admin_url_namespace
.. automethod:: get_admin_base_path
.. automethod:: get_chooser_admin_url_namespace

Wyświetl plik

@ -351,6 +351,10 @@ The delete bulk action view now also calls the `{before,after}_delete_snippet` h
If you have customised the `IndexView` and/or `DeleteView` views in a `SnippetViewSet` subclass, make sure that the `delete_multiple_url_name` attribute is renamed to `delete_url_name`.
### Snippets index views template name changed
The template name for the index view of a snippet model has changed from `wagtailsnippets/snippets/type_index.html` and `wagtailsnippets/snippets/results.html` to `wagtailsnippets/snippets/index.html` and `wagtailsnippets/snippets/index_results.html`. In addition, the model index view that lists the snippet types now looks for the template `wagtailsnippets/snippets/model_index.html` before resorting to the generic index template. If you have customised these templates, make sure to update them accordingly.
### `status` classes are now `w-status`
Please update any custom styling or usage within the admin when working with status tags to the following new classes.

Wyświetl plik

@ -577,7 +577,24 @@ The {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.list_display` attribu
You can add the ability to filter the listing view by defining a {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.list_filter` attribute and specifying the list of fields to filter. Wagtail uses the django-filter package under the hood, and this attribute will be passed as django-filter's `FilterSet.Meta.fields` attribute. This means you can also pass a dictionary that maps the field name to a list of lookups. If you would like to customise it further, 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).
For example:
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:
1. `templates/wagtailsnippets/snippets/{app_label}/{model_name}/`
2. `templates/wagtailsnippets/snippets/{app_label}/`
3. `templates/wagtailsnippets/snippets/`
So, to override the template used by the `IndexView` for example, you could create a new `index.html` template and put it in one of those locations. For example, if you wanted to do this for a `Shirt` model in a `shirts` app, you could add your custom template as `shirts/templates/wagtailsnippets/snippets/shirts/shirt/index.html`.
For some common views, Wagtail also allows you to override the template used by either specifying the `{view_name}_template_name` attribute or overriding the `get_{view_name}_template()` method on the viewset. The following is a list of customisation points for the views:
- `IndexView`: `index.html`, {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.index_template_name`, or {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_index_template()`
- For the results fragment used in AJAX responses (e.g. when searching), customise `index_results.html`, {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.index_results_template_name`, or {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_index_results_template()`.
- `CreateView`: `create.html`, {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.create_template_name`, or {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_create_template()`
- `EditView`: `edit.html`, {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.edit_template_name`, or {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_edit_template()`
- `DeleteView`: `delete.html`, {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.delete_template_name`, or {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_delete_template()`
- `HistoryView`: `history.html`, {attr}`~wagtail.snippets.views.snippets.SnippetViewSet.history_template_name`, or {meth}`~wagtail.snippets.views.snippets.SnippetViewSet.get_history_template()`
An example of a custom `SnippetViewSet` subclass:
```python
# views.py
@ -600,7 +617,7 @@ class MemberViewSet(SnippetViewSet):
# list_filter = {"shirt_size": ["exact"], "name": ["icontains"]}
```
Then, pass the viewset to the `register_snippet` call.
The viewset can be passed to the `register_snippet` call:
```python
# wagtail_hooks.py

Wyświetl plik

@ -672,3 +672,57 @@ class TestListViewWithCustomColumns(WagtailTestUtils, TestCase):
# The bulk actions column plus 4 columns defined in FullFeaturedSnippetViewSet
self.assertTagInHTML("<th>", html, count=5, allow_extra_attrs=True)
class TestCustomTemplates(WagtailTestUtils, TestCase):
model = FullFeaturedSnippet
def setUp(self):
self.user = self.login()
@classmethod
def setUpTestData(cls):
cls.object = cls.model.objects.create(text="Some snippet")
def get_url(self, view_name, args=()):
return reverse(self.model.snippet_viewset.get_url_name(view_name), args=args)
def test_template_lookups(self):
pk = quote(self.object.pk)
cases = {
"with app label and model name": (
"add",
[],
"wagtailsnippets/snippets/tests/fullfeaturedsnippet/create.html",
),
"with app label": (
"edit",
[pk],
"wagtailsnippets/snippets/tests/edit.html",
),
"without app label and model name": (
"delete",
[pk],
"wagtailsnippets/snippets/delete.html",
),
"override a view that uses a generic template": (
"unpublish",
[pk],
"wagtailsnippets/snippets/tests/fullfeaturedsnippet/unpublish.html",
),
"override with index_template_name": (
"list",
[],
"tests/fullfeaturedsnippet_index.html",
),
"override with get_history_template": (
"history",
[pk],
"tests/snippet_history.html",
),
}
for case, (view_name, args, template_name) in cases.items():
with self.subTest(case=case):
response = self.client.get(self.get_url(view_name, args=args))
self.assertTemplateUsed(response, template_name)
self.assertContains(response, "<p>An added paragraph</p>", html=True)

Wyświetl plik

@ -1158,21 +1158,51 @@ class SnippetViewSet(ViewSet):
return templates
def get_index_template(self):
"""
Returns a template to be used when rendering ``index_view``. If a
template is specified by the ``index_template_name`` attribute, that will
be used. Otherwise, a list of preferred template names are returned.
"""
return self.index_template_name or self.get_templates("index")
def get_index_results_template(self):
"""
Returns a template to be used when rendering ``index_results_view``. If a
template is specified by the ``index_results_template_name`` attribute, that will
be used. Otherwise, a list of preferred template names are returned.
"""
return self.index_results_template_name or self.get_templates("index_results")
def get_create_template(self):
"""
Returns a template to be used when rendering ``create_view``. If a
template is specified by the ``create_template_name`` attribute, that will
be used. Otherwise, a list of preferred template names are returned.
"""
return self.create_template_name or self.get_templates("create")
def get_edit_template(self):
"""
Returns a template to be used when rendering ``edit_view``. If a
template is specified by the ``edit_template_name`` attribute, that will
be used. Otherwise, a list of preferred template names are returned.
"""
return self.edit_template_name or self.get_templates("edit")
def get_delete_template(self):
"""
Returns a template to be used when rendering ``delete_view``. If a
template is specified by the ``delete_template_name`` attribute, that will
be used. Otherwise, a list of preferred template names are returned.
"""
return self.delete_template_name or self.get_templates("delete")
def get_history_template(self):
"""
Returns a template to be used when rendering ``history_view``. If a
template is specified by the ``history_template_name`` attribute, that will
be used. Otherwise, a list of preferred template names are returned.
"""
return self.history_template_name or self.get_templates("history")
def get_admin_url_namespace(self):

Wyświetl plik

@ -0,0 +1,7 @@
{% extends "wagtailsnippets/snippets/index.html" %}
{% block content %}
{{ block.super }}
<p>An added paragraph</p>
{% endblock content %}

Wyświetl plik

@ -0,0 +1,7 @@
{% extends "wagtailsnippets/snippets/history.html" %}
{% block content %}
{{ block.super }}
<p>An added paragraph</p>
{% endblock content %}

Wyświetl plik

@ -0,0 +1,7 @@
{% extends "wagtailsnippets/snippets/delete.html" %}
{% block content %}
{{ block.super }}
<p>An added paragraph</p>
{% endblock content %}

Wyświetl plik

@ -0,0 +1,7 @@
{% extends "wagtailsnippets/snippets/edit.html" %}
{% block content %}
{{ block.super }}
<p>An added paragraph</p>
{% endblock content %}

Wyświetl plik

@ -0,0 +1,7 @@
{% extends "wagtailsnippets/snippets/create.html" %}
{% block content %}
{{ block.super }}
<p>An added paragraph</p>
{% endblock content %}

Wyświetl plik

@ -0,0 +1,7 @@
{% extends "wagtailadmin/generic/confirm_unpublish.html" %}
{% block content %}
{{ block.super }}
<p>An added paragraph</p>
{% endblock content %}

Wyświetl plik

@ -247,6 +247,10 @@ class FullFeaturedSnippetViewSet(SnippetViewSet):
chooser_per_page = 15
filterset_class = FullFeaturedSnippetFilterSet
list_display = ["text", "country_code", "get_foo_country_code", UpdatedAtColumn()]
index_template_name = "tests/fullfeaturedsnippet_index.html"
def get_history_template(self):
return "tests/snippet_history.html"
class DraftStateModelViewSet(SnippetViewSet):