I have a wagtail installation using the Multisite pattern, where I have a group of user per site and each group as it's own collection.
When the User logged in the admin interface, they see in the Summary section the image count from all the collections.
But when they click the image menu, they only see the images within their group collection. I found it confusing that they could know the total count of all collections. I wanted to get the count from the collection the user had rights for.
I figured out I could override the ImagesSummaryItem and I ended up coding the following snippet of code:
class CorrectedImagesSummaryItem(SummaryItem):
order = 200
template = 'wagtailimages/homepage/site_summary_images.html'
def get_context(self):
site_name = get_site_for_user(self.request.user)['site_name']
permissions = Permission.objects.filter(
content_type=ContentType.objects.get_for_model(get_image_model()),
codename__in=['change_image', 'add_image'])
collections = Collection.objects.filter(
group_permissions__group__in=self.request.user.groups.all(),
group_permissions__permission__in=permissions
).distinct()
if collections:
image_count = get_image_model().objects.filter(collection__in=collections).count()
else:
image_count = 0
return {
'total_images': image_count,
'site_name': site_name,
}
def is_shown(self):
return permission_policy.user_has_any_permission(
self.request.user, ['change', 'add']
)
@hooks.register('construct_homepage_summary_items')
def add_corrected_images_summary_panel(request, items):
"""Replaces the Images summary panel to hide variants."""
for index, item in enumerate(items):
if item.__class__ is ImagesSummaryItem:
items[index] = CorrectedImagesSummaryItem(request)
This actually works fine, I am now showing the proper images count on the summary section but I am wondering is there a better way to query the collections of the user? Are these querysets right?
permissions = Permission.objects.filter(
content_type=ContentType.objects.get_for_model(get_image_model()),
codename__in=['change_image', 'add_image'])
collections = Collection.objects.filter(
group_permissions__group__in=self.request.user.groups.all(),
group_permissions__permission__in=permissions
).distinct()
Update
I ended up customizing the queryset for the images selection in order to only show the images within the collection the user was having access to.
In addition of the first function, I added the following code in my wagtail_hooks.py file.
@hooks.register('construct_image_chooser_queryset')
def show_collection_images_only(images, request):
# Show only the images from the collection the User has access.
collections = get_collections_from_group_permissions(request.user, ['change_image', 'add_image'])
images = images.filter(collection__in=collections)
return images
The get_collections_from_group_permissions is just a simplified function that returns exactly the Collection out of the Groups permissions the User has.
def get_collections_from_group_permissions(user, permissions):
"""
This function gets the Collections from the user groups permissions.
:param user: the user
:param permissions: the requested permissions on a Collection object
:returns: the Collections the selected User has access rights for.
"""
permissions = Permission.objects.filter(
content_type=ContentType.objects.get_for_model(get_image_model()),
codename__in=permissions)
collections = Collection.objects.filter(
group_permissions__group__in=user.groups.all(),
group_permissions__permission__in=permissions
).distinct()
return collections
With this in place, the Summary Item for the images is the number of images within the collections the User can access and when he clicks on a ImageChooserField and gets to the Image chooser, he only gets to see what is in the collections he has been granted access.
