Open bcdickinson opened 2 years ago
@bcdickinson I am confused by the "0": "my_block_type", # Default value for "my_block_type"
. Is "0"
the value?
If the issue we are trying to solve is the fact that the block "descriptor" (not sure what to call it) starts with a number (because we don't know the name of the field on the parent), could we just use something generic as the start for the string like "self__0__my_block_type__some_field": ...
?
@tbrlpld
I am confused by the "0": "my_block_type", # Default value for "my_block_type". Is "0" the value?
In this case, this means that the 0th item in the generated StreamValue
would get the default value for the my_block_type
declaration - in this case it will be the default value of MyBlockTypeFactory
.
@bcdickinson it might be worth changing StreamFieldFactory
so it is a SubFactory
subclass - that way one could provide a defaults dict in the declaration. From a high level this wouldn't be too difficult.
To allow specifying StreamBlockFactory
defaults on the Meta
class, I think we'd have to further extend StreamBlockStepBuilder
. One way would be to update its __init__
method to merge extras
and factory_meta.default_data
before doing the work that generates the actual factory class that's used for object generation.
Question: given a StreamBlockFactory
definition like this:
class BodyFactory(StreamBlockFactory):
struct_1 = SubFactory(Struct1Factory)
struct_2 = SubFactory(Struct2Factory)
class Meta:
default_data = {"0": "struct_1", "1": "struct_1"}
and a call like MyPageFactory(body__1="struct_2")
, would you expect the declarations to be merged such that you effectively end up generating data from
{
"0": "struct_1", # from meta.default_data,
"1": "struct_2", # from extras at page factory instantiation
}
?
Potentially related: #60
I found, you can use factory boy's post_generation
decorator to create a default set of blocks. Of course, this is only on the page where the block is used and not the block itself, but it's something.
class InformationPageFactory(wagtail_factories.PageFactory):
class Meta:
model = std_models.InformationPage
title = factory.Faker("text", max_nb_chars=25)
introduction = factory.Faker("text", max_nb_chars=200)
@factory.post_generation
def body(obj, create, extracted, **kwargs):
blocks = kwargs or {"0": "paragraph"}
obj.body = utils_factories.StoryBlockFactory(**blocks)
This is a pre-emptive issue ahead of the merge of #55 to document a missing feature without unnecessarily holding up that PR. The PR adds a new
StreamBlockFactory
class that can be passed as the argument to aStreamFieldFactory
declaration. The missing feature is the ability to specify the default value of aStreamBlockFactory
subclass, either when it's passed toStreamFieldFactory
or on the class definition itself.The relationship between
StreamFieldFactory
andStreamBlockFactory
is a bit like the relationship betweenSubFactory
andFactory
, so it'd be nice to be able to do something similar to the**kwargs
thatSubFactory.__call__
accepts to set the default value of the generated stream data. However, the values will always start with block indexes (e.g.0__my_block_type__some_attribute="foo"
) which aren't legal Python kwarg names, so my proposal for this API would be to accept an optionaldict
-like object that defines the defaults, something like:The above should work well for defining default data for a given use of a
StreamBlockFactory
, it would also be useful to be able to specify default values as part of theStreamBlockFactory
definition as well, so that the same data could be used in multiple places without being redefined. I'm less sure how the API for this should look, but one idea might be adding a newdefault_data
member to theMeta
class, something like this: