I am using factory_boy
to build some fixtures in Django.
I want to use factory.LazyAttribute
to build one attribute based on the condition of another attribute.
class MyFactory(factory.django.DjangoModelFactory):
class Meta:
model = MyModel
title = 'My Title' if random() < 0.5 else None
description = factory.LazyAttribute(
lambda a: factory.Faker(
'paragraph', nb_sentences=1, variable_nb_sentences=False
) if a.title else None)
However, this returns a string
being <factory.faker.Faker object at 0x000001B10597BB20>
rather than executing the correct paragraph generation.
Where am I going wrong?
factory.Faker
is a special object: when a factory instantiates an object, it will ask the factory.Faker
proxy to get a random value from faker.
The simplest way to achieve what you're looking for is to use factory.Maybe
:
class MyFactory(factory.django.DjangoModelFactory):
class Meta:
model = MyModel
title = factory.fuzzy.FuzzyChoice(["My Title", None])
description = factory.Maybe('title', factory.Faker('paragraph'))
Note that, in the code you shared, the title = "My title" if random() < 0.5 else None
is computed exactly once, when Python parses the file. I've used factory.fuzzy.FuzzyChoice
to have that random computation performed for each object. This function also uses factory_boy's randomness management features.
Another option would be to use parameters (class Params
):
class MyFactory(factory.django.DjangoModelFactory):
class Meta:
model = MyModel
class Params:
# Items here will be available to further declarations, but won't be
# passed to the model constructor.
description_contents = factory.Faker('paragraph')
title = factory.fuzzy.FuzzyChoice(["My Title", None])
description = factory.LazyAttribute(lambda a: a.description_contents if a.title else None)