feat: Added `construct_image_chooser_queryset`, `construct_document_chooser_queryset` and `construct_page_chooser_queryset` hooks

pull/3297/merge
Gagaro 2017-02-15 18:46:28 +01:00 zatwierdzone przez Matt Westcott
rodzic b00bf70229
commit 46c9cdda15
9 zmienionych plików z 215 dodań i 25 usunięć
docs
reference
releases
wagtail
wagtailadmin
wagtaildocs
wagtailimages

Wyświetl plik

@ -7,6 +7,7 @@ Changelog
* Use minified versions of jQuery and jQuery UI in the admin. Total savings without compression 371 KB (Tom Dyson)
* Hooks can now specify the order in which they are run (Gagaro)
* Added a `submit_buttons` block to login template (Gagaro)
* Added `construct_image_chooser_queryset`, `construct_document_chooser_queryset` and `construct_page_chooser_queryset` hooks (Gagaro)
* The homepage created in the project template is now titled "Home" rather than "Homepage" (Karl Hobley)
* Signal receivers for custom `Image` and `Rendition` models are connected automatically (Mike Dingjan)
* Fix: Marked 'Date from' / 'Date to' strings in wagtailforms for translation (Vorlif)

Wyświetl plik

@ -511,6 +511,66 @@ Hooks for customising the way users are directed through the process of creating
return items.append( UserbarPuppyLinkItem() )
Choosers
--------
.. _construct_page_chooser_queryset:
``construct_page_chooser_queryset``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when rendering the page chooser view, to allow the page listing queryset to be customised. The callable passed into the hook will receive the current page queryset and the request object, and must return a Page queryset (either the original one, or a new one).
.. code-block:: python
from wagtail.wagtailcore import hooks
@hooks.register('construct_page_chooser_queryset')
def show_my_pages_only(pages, request):
# Only show own pages
pages = pages.filter(owner=request.user)
return pages
.. _construct_document_chooser_queryset:
``construct_document_chooser_queryset``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when rendering the document chooser view, to allow the document listing queryset to be customised. The callable passed into the hook will receive the current document queryset and the request object, and must return a Document queryset (either the original one, or a new one).
.. code-block:: python
from wagtail.wagtailcore import hooks
@hooks.register('construct_document_chooser_queryset')
def show_my_uploaded_documents_only(documents, request):
# Only show uploaded documents
documents = documents.filter(uploaded_by=request.user)
return documents
.. _construct_image_chooser_queryset:
``construct_image_chooser_queryset``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Called when rendering the image chooser view, to allow the image listing queryset to be customised. The callable passed into the hook will receive the current image queryset and the request object, and must return a Document queryset (either the original one, or a new one).
.. code-block:: python
from wagtail.wagtailcore import hooks
@hooks.register('construct_image_chooser_queryset')
def show_my_uploaded_images_only(images, request):
# Only show uploaded images
images = images.filter(uploaded_by=request.user)
return images
Page explorer
-------------

Wyświetl plik

@ -17,6 +17,7 @@ Other features
* Use minified versions of jQuery and jQuery UI in the admin. Total savings without compression 371 KB (Tom Dyson)
* Hooks can now specify the order in which they are run (Gagaro)
* Added a ``submit_buttons`` block to login template (Gagaro)
* Added ``construct_image_chooser_queryset``, ``construct_document_chooser_queryset`` and ``construct_page_chooser_queryset`` hooks (Gagaro)
* The homepage created in the project template is now titled "Home" rather than "Homepage" (Karl Hobley)
* Signal receivers for custom ``Image`` and ``Rendition`` models are connected automatically (Mike Dingjan)

Wyświetl plik

@ -27,6 +27,21 @@ class TestChooserBrowse(TestCase, WagtailTestUtils):
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'wagtailadmin/chooser/browse.html')
def test_construct_queryset_hook(self):
page = SimplePage(title="Test shown", content="hello")
Page.get_first_root_node().add_child(instance=page)
page_not_shown = SimplePage(title="Test not shown", content="hello")
Page.get_first_root_node().add_child(instance=page_not_shown)
def filter_pages(pages, request):
return pages.filter(id=page.id)
with self.register_hook('construct_page_chooser_queryset', filter_pages):
response = self.get()
self.assertEqual(len(response.context['pages']), 1)
self.assertEqual(response.context['pages'][0].specific, page)
class TestCanChooseRootFlag(TestCase, WagtailTestUtils):
def setUp(self):
@ -297,6 +312,21 @@ class TestChooserSearch(TestCase, WagtailTestUtils):
response = self.get({'page_type': 'foo'})
self.assertEqual(response.status_code, 404)
def test_construct_queryset_hook(self):
page = SimplePage(title="Test shown", content="hello")
self.root_page.add_child(instance=page)
page_not_shown = SimplePage(title="Test not shown", content="hello")
self.root_page.add_child(instance=page_not_shown)
def filter_pages(pages, request):
return pages.filter(id=page.id)
with self.register_hook('construct_page_chooser_queryset', filter_pages):
response = self.get({'q': 'Test'})
self.assertEqual(len(response.context['pages']), 1)
self.assertEqual(response.context['pages'][0].specific, page)
class TestAutomaticRootPageDetection(TestCase, WagtailTestUtils):
def setUp(self):

Wyświetl plik

@ -8,6 +8,7 @@ from django.shortcuts import get_object_or_404, render
from wagtail.utils.pagination import paginate
from wagtail.wagtailadmin.forms import EmailLinkChooserForm, ExternalLinkChooserForm, SearchForm
from wagtail.wagtailadmin.modal_workflow import render_modal_workflow
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.utils import resolve_model_string
@ -75,6 +76,10 @@ def browse(request, parent_page_id=None):
# Get children of parent page
pages = parent_page.get_children()
# allow hooks to modify the queryset
for hook in hooks.get_hooks('construct_page_chooser_queryset'):
pages = hook(pages, request)
# Filter them by page type
if desired_classes != (Page,):
# restrict the page listing to just those pages that:
@ -131,15 +136,20 @@ def search(request, parent_page_id=None):
except (ValueError, LookupError):
raise Http404
pages = Page.objects.all()
# allow hooks to modify the queryset
for hook in hooks.get_hooks('construct_page_chooser_queryset'):
pages = hook(pages, request)
search_form = SearchForm(request.GET)
if search_form.is_valid() and search_form.cleaned_data['q']:
pages = Page.objects.exclude(
pages = pages.exclude(
depth=1 # never include root
)
pages = filter_page_type(pages, desired_classes)
pages = pages.search(search_form.cleaned_data['q'], fields=['title'])
else:
pages = Page.objects.none()
pages = pages.none()
paginator, pages = paginate(request, pages, per_page=25)

Wyświetl plik

@ -634,7 +634,7 @@ class TestMultipleDocumentUploader(TestCase, WagtailTestUtils):
class TestDocumentChooserView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
self.user = self.login()
def test_simple(self):
response = self.client.get(reverse('wagtaildocs:chooser'))
@ -688,6 +688,44 @@ class TestDocumentChooserView(TestCase, WagtailTestUtils):
# Check that we got the last page
self.assertEqual(response.context['documents'].number, response.context['documents'].paginator.num_pages)
def test_construct_queryset_hook_browse(self):
document = Document.objects.create(
title="Test document shown",
uploaded_by_user=self.user,
)
Document.objects.create(
title="Test document not shown",
)
def filter_documents(documents, request):
# Filter on `uploaded_by_user` because it is
# the only default FilterField in search_fields
return documents.filter(uploaded_by_user=self.user)
with self.register_hook('construct_document_chooser_queryset', filter_documents):
response = self.client.get(reverse('wagtaildocs:chooser'))
self.assertEqual(len(response.context['documents']), 1)
self.assertEqual(response.context['documents'][0], document)
def test_construct_queryset_hook_search(self):
document = Document.objects.create(
title="Test document shown",
uploaded_by_user=self.user,
)
Document.objects.create(
title="Test document not shown",
)
def filter_documents(documents, request):
# Filter on `uploaded_by_user` because it is
# the only default FilterField in search_fields
return documents.filter(uploaded_by_user=self.user)
with self.register_hook('construct_document_chooser_queryset', filter_documents):
response = self.client.get(reverse('wagtaildocs:chooser'), {'q': 'Test'})
self.assertEqual(len(response.context['documents']), 1)
self.assertEqual(response.context['documents'][0], document)
class TestDocumentChooserChosenView(TestCase, WagtailTestUtils):
def setUp(self):

Wyświetl plik

@ -9,6 +9,7 @@ from wagtail.utils.pagination import paginate
from wagtail.wagtailadmin.forms import SearchForm
from wagtail.wagtailadmin.modal_workflow import render_modal_workflow
from wagtail.wagtailadmin.utils import PermissionPolicyChecker
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import Collection
from wagtail.wagtaildocs.forms import get_document_form
from wagtail.wagtaildocs.models import get_document_model
@ -41,12 +42,14 @@ def chooser(request):
else:
uploadform = None
documents = []
documents = Document.objects.all()
# allow hooks to modify the queryset
for hook in hooks.get_hooks('construct_document_chooser_queryset'):
documents = hook(documents, request)
q = None
is_searching = False
if 'q' in request.GET or 'p' in request.GET or 'collection_id' in request.GET:
documents = Document.objects.all()
collection_id = request.GET.get('collection_id')
if collection_id:
@ -77,16 +80,16 @@ def chooser(request):
if len(collections) < 2:
collections = None
documents = Document.objects.order_by('-created_at')
documents = documents.order_by('-created_at')
paginator, documents = paginate(request, documents, per_page=10)
return render_modal_workflow(request, 'wagtaildocs/chooser/chooser.html', 'wagtaildocs/chooser/chooser.js', {
'documents': documents,
'uploadform': uploadform,
'searchform': searchform,
'collections': collections,
'is_searching': False,
})
return render_modal_workflow(request, 'wagtaildocs/chooser/chooser.html', 'wagtaildocs/chooser/chooser.js', {
'documents': documents,
'uploadform': uploadform,
'searchform': searchform,
'collections': collections,
'is_searching': False,
})
def document_chosen(request, document_id):

Wyświetl plik

@ -412,7 +412,7 @@ class TestImageDeleteView(TestCase, WagtailTestUtils):
class TestImageChooserView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
self.user = self.login()
def get(self, params={}):
return self.client.get(reverse('wagtailimages:chooser'), params)
@ -452,6 +452,48 @@ class TestImageChooserView(TestCase, WagtailTestUtils):
# Results should not include images that just have 'even' in the title
self.assertNotContains(response, "Test image 3 is even better")
def test_construct_queryset_hook_browse(self):
image = Image.objects.create(
title="Test image shown",
file=get_test_image_file(),
uploaded_by_user=self.user,
)
Image.objects.create(
title="Test image not shown",
file=get_test_image_file(),
)
def filter_images(images, request):
# Filter on `uploaded_by_user` because it is
# the only default FilterField in search_fields
return images.filter(uploaded_by_user=self.user)
with self.register_hook('construct_image_chooser_queryset', filter_images):
response = self.get()
self.assertEqual(len(response.context['images']), 1)
self.assertEqual(response.context['images'][0], image)
def test_construct_queryset_hook_search(self):
image = Image.objects.create(
title="Test image shown",
file=get_test_image_file(),
uploaded_by_user=self.user,
)
Image.objects.create(
title="Test image not shown",
file=get_test_image_file(),
)
def filter_images(images, request):
# Filter on `uploaded_by_user` because it is
# the only default FilterField in search_fields
return images.filter(uploaded_by_user=self.user)
with self.register_hook('construct_image_chooser_queryset', filter_images):
response = self.get({'q': 'Test'})
self.assertEqual(len(response.context['images']), 1)
self.assertEqual(response.context['images'][0], image)
class TestImageChooserChosenView(TestCase, WagtailTestUtils):
def setUp(self):

Wyświetl plik

@ -9,6 +9,7 @@ from wagtail.utils.pagination import paginate
from wagtail.wagtailadmin.forms import SearchForm
from wagtail.wagtailadmin.modal_workflow import render_modal_workflow
from wagtail.wagtailadmin.utils import PermissionPolicyChecker, popular_tags_for_model
from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.models import Collection
from wagtail.wagtailimages import get_image_model
from wagtail.wagtailimages.formats import get_image_format
@ -49,6 +50,10 @@ def chooser(request):
images = Image.objects.order_by('-created_at')
# allow hooks to modify the queryset
for hook in hooks.get_hooks('construct_image_chooser_queryset'):
images = hook(images, request)
q = None
if (
'q' in request.GET or 'p' in request.GET or 'tag' in request.GET or
@ -91,16 +96,16 @@ def chooser(request):
paginator, images = paginate(request, images, per_page=12)
return render_modal_workflow(request, 'wagtailimages/chooser/chooser.html', 'wagtailimages/chooser/chooser.js', {
'images': images,
'uploadform': uploadform,
'searchform': searchform,
'is_searching': False,
'query_string': q,
'will_select_format': request.GET.get('select_format'),
'popular_tags': popular_tags_for_model(Image),
'collections': collections,
})
return render_modal_workflow(request, 'wagtailimages/chooser/chooser.html', 'wagtailimages/chooser/chooser.js', {
'images': images,
'uploadform': uploadform,
'searchform': searchform,
'is_searching': False,
'query_string': q,
'will_select_format': request.GET.get('select_format'),
'popular_tags': popular_tags_for_model(Image),
'collections': collections,
})
def image_chosen(request, image_id):