Skip to content

Instantly share code, notes, and snippets.

@quevon24
Created February 2, 2023 22:57
Show Gist options
  • Save quevon24/e2a9d0a812927d3d444306e79b98009b to your computer and use it in GitHub Desktop.
Save quevon24/e2a9d0a812927d3d444306e79b98009b to your computer and use it in GitHub Desktop.
Pass data on the fly to factory_boy factory using custom RelatedFactoryList class
import copy
from factory import RelatedFactoryList
class RelatedFactoryVariableList(RelatedFactoryList):
"""This factory allows you to specify how many related objects do you
want to create, but also allows you to define the data for each related
object.
Usage example:
# This will create 4 objects
FooFactory(bars__size=4)
# This will create 3 objects, with different data for each one
FooFactory(bars__data=[{"name": "a"}, {"name": "b"}, {"name": "c"}])
# Based on answer here: https://github.com/FactoryBoy/factory_boy/issues/767
"""
def call(self, instance, step, context):
size = context.extra.pop("size", None)
data = context.extra.pop("data", [])
if size and data:
if size != len(data):
raise TypeError(
"RelatedFactoryVariableList you can only use data or size, not both."
)
if not size and not data:
size = self.size
if size and not data:
# Generate size number of objects
return [
super(RelatedFactoryList, self).call(instance, step, context)
for i in range(size)
]
results = []
for d in data:
# Create copy of PostGenerationContext object
copied_context = copy.deepcopy(context)
if isinstance(d, dict):
# Update data for each factory instance
copied_context.extra.update(d)
results.append(
super(RelatedFactoryList, self).call(
instance, step, copied_context
)
)
return results
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment