Skip to main content

wagtail-multiple-chooser-block

A StreamField block to choose multiple images, documents, pages or snippets at once, like Wagtail's MultipleChooserPanel does for inline models.

MultipleChooserBlock is a ListBlock. Its "+" buttons open the chooser in multiple selection mode, and every chosen item is added to the list.

In the chooser, selected items stay selected while searching and paginating. They are listed above the confirm button, where they can also be removed from the selection.

Choosing images at once, including through search, in a MultipleChooserBlock with a live preview

Supported versions

This package supports Wagtail 7.0 and up, with the Python and Django versions supported by Wagtail.

Installation

uv add wagtail-multiple-chooser-block
pip install wagtail-multiple-chooser-block

Add it to INSTALLED_APPS, so its JavaScript is served:

INSTALLED_APPS = [
    # ...
    "wagtail_multiple_chooser_block",
]

Usage

Use it in place of a ListBlock of a chooser block:

from wagtail.images.blocks import ImageChooserBlock

from wagtail_multiple_chooser_block.blocks import MultipleChooserBlock


class GalleryBlock(StructBlock):
    images = MultipleChooserBlock(ImageChooserBlock())

It works with any chooser block: ImageChooserBlock, DocumentChooserBlock, PageChooserBlock, SnippetChooserBlock, and chooser blocks of your own chooser viewsets.

For items with more fields than the chooser, use a StructBlock and name the chooser block with chooser_field_name, like MultipleChooserPanel does:

class CaptionedImageBlock(StructBlock):
    image = ImageChooserBlock()
    caption = CharBlock(required=False)


images = MultipleChooserBlock(CaptionedImageBlock(), chooser_field_name="image")
images = MultipleChooserBlock(ImageBlock(), chooser_field_name="image")

The value is stored the same way as a ListBlock, so changing a ListBlock into a MultipleChooserBlock needs a migration, but no data migration.

Options

Besides the options of ListBlock, such as min_num and max_num:

  • chooser_field_name: the chooser block within a StructBlock child.
  • allow_duplicates: whether an item can be chosen more than once. Defaults to True, like MultipleChooserPanel. With False, items that are already in the list can't be selected in the chooser.

With max_num, the chooser only lets you select as many items as the list has room for, and the "+" buttons are disabled once the list is full.

Bulk upload

The optional bulk_upload app puts Wagtail's bulk upload for images and documents in the upload tab of the chooser, the same one as in Wagtail's "Add images" and "Add documents" views. When all uploads succeed, the uploaded items are added to the list straight away, along with the items selected in the chooser. Otherwise, the chooser stays open with the status of each upload, and "Confirm selection" adds the uploaded items. A duplicate image then has the choice of Wagtail's image chooser, between the new and the existing image, and an upload that needs more details, such as for a required field of a custom image model, has its form.

Add it to INSTALLED_APPS:

INSTALLED_APPS = [
    # ...
    "wagtail_multiple_chooser_block",
    "wagtail_multiple_chooser_block.contrib.bulk_upload",
]

Then use its chooser blocks in a MultipleChooserBlock:

from wagtail_multiple_chooser_block.contrib.bulk_upload.blocks import (
    BulkUploadDocumentChooserBlock,
    BulkUploadImageBlock,
    BulkUploadImageChooserBlock,
)

images = MultipleChooserBlock(BulkUploadImageChooserBlock())
images = MultipleChooserBlock(BulkUploadImageBlock(), chooser_field_name="image")
documents = MultipleChooserBlock(BulkUploadDocumentChooserBlock())

They are Wagtail's ImageChooserBlock, ImageBlock and DocumentChooserBlock, with a chooser that has the bulk upload, and store the same values. Outside a MultipleChooserBlock, their chooser is the same as Wagtail's.

Development

uv sync
uv run playwright install chromium

Format and lint:

uv run ruff format .
uv run ruff check --fix .

Run the tests. They edit a page in the Wagtail admin with a real browser, through Playwright:

uv run pytest

Run the tests against the supported Python, Django and Wagtail versions with tox:

uv run tox run-parallel
uv run tox run -e py313-django52-wagtail70

Releases

  1. Update the version in pyproject.toml.
  2. Commit, tag and push: git commit -am "Release v0.1.0" && git tag v0.1.0 && git push --follow-tags.
  3. Create a GitHub release from the tag. CI publishes it to PyPI.

License

MIT

Release files for wagtail-multiple-chooser-block 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wagtail-multiple-chooser-block 0.2.0
File Size Uploaded
wagtail_multiple_chooser_block-0.2.0.tar.gz 4.0 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for wagtail-multiple-chooser-block 0.2.0
File Interpreter ABI Platform
wagtail_multiple_chooser_block-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 4.1 MB

Release files / wagtail_multiple_chooser_block-0.2.0.tar.gz

Download URL wagtail_multiple_chooser_block-0.2.0.tar.gz
Size 4.0 MB
Tags Source
SHA-256 checksum
How to use checksums
a2686b8f0e563a0591f22df6e5904b373ecf1f49a931cafcbca427c3e9822e3f
BLAKE2b-256 checksum
How to use checksums
e2eddaa97b42c2a57c8b1fd76db67f366d66f98fd7b8a757eacc1697771c6855
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / wagtail_multiple_chooser_block-0.2.0-py3-none-any.whl

Download URL wagtail_multiple_chooser_block-0.2.0-py3-none-any.whl
Size 21.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e84bb24c995e26f5a0a17c1fe206b09fbe6db1c3e9d8b2f12d870ea61a10ca5d
BLAKE2b-256 checksum
How to use checksums
0601ed254e0ccfd8f8e0ea05eee7ab73cb9b0394bf4656d6be8b1fdd4cad8984
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page