Description
# wagtail-factories Factory boy classes for Wagtail CMS ## Installation ``` shell pip install wagtail-factories ``` ## Usage Documentation is still in progress, but see the [tests](https://github.com/wagtail/wagtail-factories/tree/main/tests) for more examples. ``` python import wagtail_factories from wagtail import models as wt_models from . import models class MyCarouselItemFactory(wagtail_factories.StructBlockFactory): label = 'my-label' image = factory.SubFactory( wagtail_factories.ImageChooserBlockFactory) class Meta: model = models.MyBlockItem class MyCarouselFactory(wagtail_factories.StructBlockFactory): title = "Carousel title" items = wagtail_factories.ListBlockFactory( MyCarouselItemFactory) class Meta: model = models.MyCarousel class MyNewsPageFactory(wagtail_factories.PageFactory): class Meta: model = models.MyNewsPage class MyNewsPageChooserBlockFactory(wagtail_factories.PageChooserBlockFactory): page = factory.SubFactory(MyNewsPageFactory) class MyTestPageFactory(wagtail_factories.PageFactory): body = wagtail_factories.StreamFieldFactory({ 'carousel': factory.SubFactory(MyCarouselFactory), 'news_page': factory.SubFactory(MyNewsPageChooserBlockFactory), }) class Meta: model = models.MyTestPage def test_my_page(): root_page = wt_models.Page.get_first_root_node() assert root_page is not None my_page = MyTestPageFactory( parent=root_page, title="My great page", body__0__carousel__items__0__label='Slide 1', body__0__carousel__items__0__image__image__title='Image Slide 1', body__0__carousel__items__1__label='Slide 2', body__0__carousel__items__1__image__image__title='Image Slide 2', body__0__carousel__items__2__label='Slide 3', body__0__carousel__items__2__image__image__title='Image Slide 3', body__1__news_page__page__title="News", ) # Defaults defined on factory classes are propagated. assert my_page.body[0].value["title"] == "Carousel title" # Parameters are propagated. assert my_page.title == "My great page" assert my_page.body[0].value["items"][0].value["label"] == "Slide 1" ``` ### Using StreamBlockFactory `StreamBlockFactory` can be used in conjunction with the other block factory types to create complex, nested `StreamValues`, much like how `StreamBlock` can be used to declare the blocks for a complex `StreamField`. First, define your `StreamBlockFactory` subclass, using `factory.SubFactory` to wrap child block declarations. Be sure to include your `StreamBlock` subclass as the model attribute on the inner `Meta` class. ``` python class MyStreamBlockFactory(wagtail_factories.StreamBlockFactory): my_struct_block = factory.SubFactory(MyStructBlockFactory) class Meta: model = MyStreamBlock ``` Then include your `StreamBlockFactory` subclass on a model factory as the argument to a `StreamFieldFactory`. ``` python class MyPageFactory(wagtail_factories.PageFactory): body = wagtail_factories.StreamFieldFactory(MyStreamBlockFactory) class Meta: model = MyPage ``` You can then use a modified version of factory\_boy\'s deep object declaration syntax to build up `StreamValues` on the fly. ``` python MyPageFactory( body__0__my_struct_block__some_field="some value", body__0__my_struct_block__some_other_field="some other value", ) ``` To generate the default value for a block factory, terminate your declaration at the index and provide the block name as the value. ``` python MyPageFactory(body__0="my_struct_block") ``` ### Alternative StreamFieldFactory declaration syntax Prior to version 3.0, `StreamFieldFactory` could only be used by providing a dict mapping block names to block factory classes as the single argument, for example: ``` python class MyTestPageWithStreamFieldFactory(wagtail_factories.PageFactory): body = wagtail_factories.StreamFieldFactory( { "char_array": wagtail_factories.ListBlockFactory( wagtail_factories.CharBlockFactory ), "int_array": wagtail_factories.ListBlockFactory( wagtail_factories.IntegerBlockFactory ), "struct": MyBlockFactory, "image": wagtail_factories.ImageChooserBlockFactory, } ) class Meta: model = models.MyTestPage ``` This style of declaration is still supported, with the caveat that nested stream blocks are not supported for this approach. From version 3.0, all `BlockFactory` values in a `StreamFieldFactory` definition of this style *must* be wrapped in factory\_boy `SubFactories`. For example, the above example must be updated to the following for 3.0 compatibility. ``` python class MyTestPageWithStreamFieldFactory(wagtail_factories.PageFactory): body = wagtail_factories.StreamFieldFactory( { "char_array": wagta
Release History
| Version | Changes | Urgency | Date |
|---|---|---|---|
| 4.4.0 | Imported from PyPI (4.4.0) | Low | 4/21/2026 |
| v4.4.0 | ## What's Changed * Add developer documentation for StreamField block factories by @jams2 in https://github.com/wagtail/wagtail-factories/pull/102 * Add end-user documentation by @jams2 in https://github.com/wagtail/wagtail-factories/pull/107 * Add support for Wagtail 7 and Python 3.14 by @nickmoreton in https://github.com/wagtail/wagtail-factories/pull/114 **Full Changelog**: https://github.com/wagtail/wagtail-factories/compare/v4.3.0...v4.4.0 | Low | 2/10/2026 |
| v4.3.0 | ## What's Changed * Update for Wagtail 6.3 by @JakubMastalerz in https://github.com/wagtail/wagtail-factories/pull/96 * Wagtail 7.0 maintenance by @nickmoreton in https://github.com/wagtail/wagtail-factories/pull/100 * Add Wagtail 7.1 support by @jams2 in https://github.com/wagtail/wagtail-factories/pull/101 * Create ImageBlockFactory by @mgax in https://github.com/wagtail/wagtail-factories/pull/98 * Bump version 4.2.1 → 4.3.0 by @jams2 in https://github.com/wagtail/wagtail-factories/pull/1 | Low | 8/15/2025 |
| 4.2.1 | ## What's Changed This release fixes an issue with the PyPI release process. | Low | 5/26/2024 |
| 4.2.0 | ## What's Changed * Chore/update tooling by @jams2 in https://github.com/wagtail/wagtail-factories/pull/84 * Add handling for StructBlock classes with custom StructValues by @jams2 in https://github.com/wagtail/wagtail-factories/pull/76 * Wagtail 6.1 - Minor updates by @katdom13 in https://github.com/wagtail/wagtail-factories/pull/91 ## New Contributors * @katdom13 made their first contribution in https://github.com/wagtail/wagtail-factories/pull/91 **Full Changelog**: https://github.c | Low | 5/24/2024 |
| v4.1.0 | This release adds support for Wagtail 5.0, and drops support for Wagtail < 4.1. The upper bound on the Wagtail version was also removed to ease the upgrade path in future. ## What's Changed * Add Wagtail 5.0 support, drop Wagtail < 4.1 support by @jams2 and @nickmoreton in https://github.com/wagtail/wagtail-factories/pull/74 **Full Changelog**: https://github.com/wagtail/wagtail-factories/compare/4.0.0...v4.1.0 | Low | 5/16/2023 |
| 4.0.0 | This release fixes a compatibility issue with Wagtail 4.1 (see https://github.com/wagtail/wagtail-factories/pull/68 for details). When running on Wagtail >= 2.16 `ListBlockFactory` now returns a `wagtail.blocks.list_block.ListValue` instead of a plain `list`, in line with Wagtail's behaviour. | Low | 12/2/2022 |
| 3.1.0 | Adds `PageChooserBlock` and `DocumentChooserBlock` | Low | 7/28/2022 |
| 3.0.0 | - Add StreamBlockFactory. Breaking change to StreamFieldFactory usage - see README. | Low | 7/25/2022 |
| 2.1.0 | - Add support for Wagtail 3.0 and drop support for all Wagtail versions before 2.15 - Add support for Django 4.0 - Add support for Python 3.10 - Removed support for Python 3.6 - Removed support for Django 2.2 and 3.1 - Removed support for factory boy <3.2 | Low | 7/1/2022 |
| 2.0.1 | - Updating to support Factory Boy 3.0 | Low | 10/5/2020 |
