Wagtail has a feature called hooks
that lets you modify some of the Wagtail internal logic, this is a very helpful feature that can enable you to do this.
There is a hook called construct_image_chooser_queryset
. You will need to create a file wagtail_hooks.py
in one of your app folders, this gets run by Wagtail when the app runs.
Once you have the hook running, you can inject custom filtering of the images
results for the image chooser modal. This hook will run for various image listings throughout Wagtail so you will want to add some logic to ensure you are not filtering the images everywhere.
A potential approach would be to read the request, which is passed into the hook, to determine if the current request is for a page editing scenario. Once you know this, you can work out what page class is being used and then filter your images based on some class method on the page class.
When the request is made for the image chooser modal, you can read the HTTP_REFERRER and from that URL use Django's resolve
to determine where it was called and what page is being edited.
Example
- Using the hook described above, we read the
HTTP_REFERRER
- Use
urlparse
and resolve
to return a Django match
object
- Read the match data to confirm we are editing a page
- If editing a page, we query for that
Page
and use the specific_class
property
- Finally, we can get a collection id from the class to filter images
- Note: how you get the collection id is 100% up to you, you could hard code it, make it a separate function or even make it a specific class method, just be careful to ensure that it will all work if that method is not available on ALL pages.
- Test this across other image choosers to ensure nothing else breaks.
- This will not 'hide' the collection drop-down on the image chooser modal, you may just need to do this with CSS or JS unfortunately.
wagtail_hooks.py
from django.urls import resolve
from urllib.parse import urlparse
from wagtail.core import hooks
from wagtail.core.models import Page
@hooks.register('construct_image_chooser_queryset')
def show_images_for_specific_collections_on_page_editing(images, request):
# first - pull out the referrer for this current AJAX call
http_referrer = request.META.get('HTTP_REFERER', None) or '/'
# second - use django utils to find the matched view
match = resolve(urlparse(http_referrer)[2])
# if we are editing a page we can restrict the available images
if (match.app_name is 'wagtailadmin_pages') and (match.url_name is 'edit'):
page = Page.objects.get(pk=match.args[0])
# important: wrap in a try/except as this may not be implemented on all pages
image_collection_id = page.specific_class.get_image_collection()
# return filtered images
return images.filter(collection=image_collection_id)
return images
models.py
from wagtail.core.models import Page
class BlogPage(Page):
# ...
@classmethod
def get_image_collection(cls):
# any logic here to determine what collection to filter by
return 4