7

I am thinking about migrating an existing webpage to wagtail. However, a major part of the page are image galleries, with a total of some thousand images and some hundred galleries. Furthermore, the page is divided into several sites, with editors only allowed to change the content for one specific site.

Since the collections are not hierachical, they do not provide a convenient way to collect images into image galleries, the select boxes get confusingly long if their number grows.

I have defined a page-derived class that contains ParentalKey to images, which is sufficient to implement an image gallery. However, it is not very user-friendly to select, say, 200 images for the gallery one by one. Thus I thought I should extend the ImageChooserPanel to something like aMultipleImageChooserPanel, which would allow selecting and uploading multiple images. The code for uploading multiple images should be available in wagtail.

After reading the code for wagtailimages/views/multiple.py, wagtailadmin/edit_handlers.py and all the corresponding parent classes, I still do not see how the modal ImageChooserPanel determines the selected image and how its id is returned. Presumably, most of this happens in JS, however, I cannot find any hint where to look for the corresponding code, nor any hints on how to extend it.

Is it possible to extend the modal ImageChooserPanel? Could anyone point me to a code snippet to start with?

Patrick Happel
  • 1,336
  • 8
  • 18
  • We are also running/looking into this. FYI there are two wagtail tickets, one specific to images [#1717](https://github.com/wagtail/wagtail/issues/1717) and once for a more general solution [#2203](https://github.com/wagtail/wagtail/issues/2203). Not much progress there yet but maybe you want to subscribe to them. – benebun Mar 15 '17 at 19:13
  • There is also a work-in-progress pull request that deals with collection hierarchies - [#3407](https://github.com/wagtail/wagtail/pull/3407) – zerolab Mar 15 '17 at 19:29
  • Thanks! I guess collections could work as a workaround (collections are best if you need to reuse galleries). – benebun Mar 17 '17 at 21:48
  • Although a general way to achieve a multi-selection ImageChooserPanel is still missing, I have found a solution for my specific problem. I have outlined the details [on github](https://github.com/wagtail/wagtail/issues/1717). – Patrick Happel Mar 26 '17 at 04:36
  • I fiddled with some choosers once: https://www.fourdigits.nl/blog/tutorial-filter-wagtail-snippets-by-tag/ – allcaps Nov 28 '19 at 22:46

3 Answers3

1

Wagtail added support for Collections with hierarchy in 2.11 (November 2020).

This makes it possible to achieve the original goal of providing an easier way to select a group of images much more maintainable. The approach is used in the Wagtail bakery demo application for this very same purpose (see GalleryPage).

Code Example

Below are the relevant code snippets to achieve a similar approach.

models.py

from django import forms
from django.db import models

from wagtail.admin.edit_handlers import FieldPanel
from wagtail.core.models import Collection, Page
from wagtail.images import get_image_model


class CustomSelect(forms.Select):
    """Allow for visual representation of 'depth' of collection in select"""

    def create_option(self, name, value, *args, **kwargs):
        option_dict = super().create_option(name, value, *args, **kwargs)
        instance = getattr(value, 'instance', None)
        if instance:
            option_dict['label'] = instance.get_indented_name()
        return option_dict

class GalleryPage(Page):

    collection = models.ForeignKey(
        Collection,
        limit_choices_to=~models.Q(name__in=['Root']), # do not allow 'root' selection
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        help_text='Select the image collection for this gallery.'
    )

    content_panels = Page.content_panels + [
        FieldPanel('collection', widget=CustomSelect),
        # ... other panels
    ]

    def get_collection_images(self):
        return get_image_model().objects.filter(collection=self.collection)

gallery_page.html

{% extends "base.html" %}
{% load wagtailimages_tags %}

{% block content %}
<div class="row">
  {% for img in page.get_collection_images %}
    {% image img fill-285x200-c100 as img_obj %}
    <div class="col-sm-6">
      <figure class="gallery-figure">
          <img src="{{img_obj.url}}" class="img-responsive" />
          <figcaption>{{ img.title }}</figcaption>
      </figure>
    </div>
  {% endfor %}
</div>
{% endblock content %}

LB Ben Johnston
  • 4,751
  • 13
  • 29
1

Update: As of Wagtail 4.2 (February 2023) this is now a native feature

A new panel type MultipleChooserPanel is now available. This is a variant of InlinePanel which improves the editor experience when adding large numbers of linked item - rather than creating and populating each sub-form individually, a chooser modal is opened allowing multiple objects to be selected at once.

# ... other imports
from wagtail.admin.panels import FieldPanel, MultipleChooserPanel


class BlogPageGalleryImage(Orderable):
    """
    Example related image
    """

    page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')
    image = models.ForeignKey(
        'wagtailimages.Image', on_delete=models.CASCADE, related_name='+'
    )
    caption = models.CharField(blank=True, max_length=250)

    panels = [
        FieldPanel('image'),
        FieldPanel('caption'),
    ]


class BlogPage(Page:
    # ... other fields

    # Used in the same way as `InlinePanel`
    content_panels = Page.content_panels + [
        MultipleChooserPanel(
            'gallery_images',
            label="Gallery images",
            chooser_field_name="image",
        )
    ]

Example pulled from release notes & docs

LB Ben Johnston
  • 4,751
  • 13
  • 29
0

@chris-h wrote a rather nice answer in a similar issue, where you can use the ImageChooserBlock instead of a custom dropdown select form: https://stackoverflow.com/a/57215050

I like that answer because it makes for a better UX.

greenie-beans
  • 440
  • 1
  • 5
  • 15
  • The downside of this approach is that it does not use Django models, but StreamField. There are pros (simpler, nicer UX) but also cons (no proper migration support or full Django query support). – LB Ben Johnston Mar 15 '23 at 10:38