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.
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 aStructBlockchild.allow_duplicates: whether an item can be chosen more than once. Defaults toTrue, likeMultipleChooserPanel. WithFalse, 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
- Update the version in
pyproject.toml. - Commit, tag and push:
git commit -am "Release v0.1.0" && git tag v0.1.0 && git push --follow-tags. - 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)
| File | Size | Uploaded | |
|---|---|---|---|
| wagtail_multiple_chooser_block-0.2.0.tar.gz | 4.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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