0
# Helper Functions and Utilities
1
2
Convenience functions for direct object creation, debugging tools, factory generation utilities, and functional-style declaration wrappers. These utilities provide alternative ways to use Factory Boy and simplify common patterns.
3
4
## Capabilities
5
6
### Direct Object Creation Functions
7
8
Standalone functions for creating objects without defining factory classes, useful for simple cases and one-off object generation.
9
10
```python { .api }
11
def build(klass, **kwargs):
12
"""
13
Build single instance of a class without persistence.
14
15
Args:
16
klass: Class to instantiate
17
**kwargs: Attribute values for the instance
18
19
Returns:
20
Instance of klass
21
"""
22
23
def create(klass, **kwargs):
24
"""
25
Create single instance of a class with persistence.
26
27
Args:
28
klass: Class to instantiate
29
**kwargs: Attribute values for the instance
30
31
Returns:
32
Persisted instance of klass
33
"""
34
35
def stub(klass, **kwargs):
36
"""
37
Create stub object with attributes only (no persistence).
38
39
Args:
40
klass: Class to use as model reference
41
**kwargs: Attribute values for the stub
42
43
Returns:
44
StubObject with specified attributes
45
"""
46
47
def generate(klass, strategy, **kwargs):
48
"""
49
Generate instance using specified strategy.
50
51
Args:
52
klass: Class to instantiate
53
strategy (str): 'build', 'create', or 'stub'
54
**kwargs: Attribute values for the instance
55
56
Returns:
57
Instance created with specified strategy
58
"""
59
60
def simple_generate(klass, create, **kwargs):
61
"""
62
Generate instance with boolean create flag.
63
64
Args:
65
klass: Class to instantiate
66
create (bool): True for create strategy, False for build
67
**kwargs: Attribute values for the instance
68
69
Returns:
70
Instance created with specified strategy
71
"""
72
```
73
74
#### Usage Examples
75
76
```python
77
from factory.helpers import build, create, stub, generate, simple_generate
78
79
# Direct object creation without factory classes
80
user = build(User, name='Test User', email='test@example.com')
81
user = create(User, name='Persistent User', email='persist@example.com')
82
user = stub(User, name='Stub User', email='stub@example.com')
83
84
# Using strategy parameter
85
user = generate(User, 'build', name='Generated User')
86
user = simple_generate(User, create=False, name='Simple User')
87
```
88
89
### Batch Object Creation Functions
90
91
Functions for creating multiple objects at once without factory classes.
92
93
```python { .api }
94
def build_batch(klass, size, **kwargs):
95
"""
96
Build multiple instances without persistence.
97
98
Args:
99
klass: Class to instantiate
100
size (int): Number of instances to create
101
**kwargs: Attribute values for all instances
102
103
Returns:
104
List of instances
105
"""
106
107
def create_batch(klass, size, **kwargs):
108
"""
109
Create multiple instances with persistence.
110
111
Args:
112
klass: Class to instantiate
113
size (int): Number of instances to create
114
**kwargs: Attribute values for all instances
115
116
Returns:
117
List of persisted instances
118
"""
119
120
def stub_batch(klass, size, **kwargs):
121
"""
122
Create multiple stub objects.
123
124
Args:
125
klass: Class to use as model reference
126
size (int): Number of stubs to create
127
**kwargs: Attribute values for all stubs
128
129
Returns:
130
List of StubObjects
131
"""
132
133
def generate_batch(klass, strategy, size, **kwargs):
134
"""
135
Generate multiple instances using specified strategy.
136
137
Args:
138
klass: Class to instantiate
139
strategy (str): 'build', 'create', or 'stub'
140
size (int): Number of instances to create
141
**kwargs: Attribute values for all instances
142
143
Returns:
144
List of instances created with specified strategy
145
"""
146
147
def simple_generate_batch(klass, create, size, **kwargs):
148
"""
149
Generate multiple instances with boolean create flag.
150
151
Args:
152
klass: Class to instantiate
153
create (bool): True for create strategy, False for build
154
size (int): Number of instances to create
155
**kwargs: Attribute values for all instances
156
157
Returns:
158
List of instances
159
"""
160
```
161
162
#### Usage Examples
163
164
```python
165
from factory.helpers import build_batch, create_batch, stub_batch
166
167
# Batch creation without factory classes
168
users = build_batch(User, 5, is_active=True)
169
users = create_batch(User, 10, department='Engineering')
170
stubs = stub_batch(User, 3, role='admin')
171
172
# Using strategy and simple_generate
173
users = generate_batch(User, 'build', 5, status='pending')
174
users = simple_generate_batch(User, create=True, size=3, verified=True)
175
```
176
177
### Factory Creation Utilities
178
179
Functions for dynamically creating factory classes from existing classes.
180
181
```python { .api }
182
def make_factory(klass, **kwargs):
183
"""
184
Create simple factory class for given class with default attributes.
185
186
Args:
187
klass: Class to create factory for
188
**kwargs: Default attribute values for the factory
189
190
Returns:
191
Factory class configured for klass
192
"""
193
```
194
195
#### Usage Examples
196
197
```python
198
from factory.helpers import make_factory
199
200
# Dynamically create factory
201
UserFactory = make_factory(
202
User,
203
name='Test User',
204
email=factory.Sequence(lambda n: f'user{n}@example.com'),
205
is_active=True
206
)
207
208
# Use like any other factory
209
user = UserFactory()
210
user = UserFactory(name='Custom Name')
211
users = UserFactory.create_batch(5)
212
213
# With complex declarations
214
PostFactory = make_factory(
215
Post,
216
title=factory.Faker('sentence'),
217
content=factory.Faker('text'),
218
author=factory.SubFactory(UserFactory),
219
published_at=factory.LazyFunction(lambda: timezone.now())
220
)
221
```
222
223
### Debugging and Inspection
224
225
Tools for debugging factory behavior and understanding object creation.
226
227
```python { .api }
228
def debug(logger='factory', stream=None):
229
"""
230
Context manager for factory debugging that logs detailed creation steps.
231
232
Args:
233
logger (str): Logger name to use (default: 'factory')
234
stream: Output stream for debug messages (default: None uses logger)
235
236
Returns:
237
Context manager for debugging factory operations
238
"""
239
```
240
241
#### Usage Examples
242
243
```python
244
from factory.helpers import debug
245
import logging
246
247
# Enable debug logging
248
logging.basicConfig(level=logging.DEBUG)
249
250
# Debug single factory call
251
with debug():
252
user = UserFactory()
253
# Logs: Building User instance
254
# Logs: Setting attribute 'name' to 'Test User'
255
# Logs: Setting attribute 'email' to 'user1@example.com'
256
# etc.
257
258
# Debug with custom stream
259
import sys
260
with debug(stream=sys.stdout):
261
users = UserFactory.create_batch(3)
262
263
# Debug with custom logger
264
with debug(logger='my_factory_debug'):
265
post = PostFactory(author__name='Custom Author')
266
```
267
268
### Functional Declaration Wrappers
269
270
Decorator functions that convert regular functions into factory declarations, enabling functional programming patterns.
271
272
```python { .api }
273
def lazy_attribute(func):
274
"""
275
Wrap function as LazyAttribute declaration.
276
277
Args:
278
func: Function that takes instance and returns attribute value
279
280
Returns:
281
LazyAttribute declaration
282
"""
283
284
def sequence(func):
285
"""
286
Wrap function as Sequence declaration.
287
288
Args:
289
func: Function that takes sequence number and returns attribute value
290
291
Returns:
292
Sequence declaration
293
"""
294
295
def lazy_attribute_sequence(func):
296
"""
297
Wrap function as LazyAttributeSequence declaration.
298
299
Args:
300
func: Function that takes (instance, sequence_number) and returns value
301
302
Returns:
303
LazyAttributeSequence declaration
304
"""
305
306
def container_attribute(func):
307
"""
308
Wrap function as ContainerAttribute declaration (non-strict mode).
309
310
Args:
311
func: Function that takes (instance, containers) and returns value
312
313
Returns:
314
ContainerAttribute declaration with strict=False
315
"""
316
317
def post_generation(func):
318
"""
319
Wrap function as PostGeneration declaration.
320
321
Args:
322
func: Function that takes (instance, create, extracted, **kwargs)
323
324
Returns:
325
PostGeneration declaration
326
"""
327
328
def iterator(func):
329
"""
330
Turn generator function into Iterator declaration.
331
332
Args:
333
func: Generator function that yields values
334
335
Returns:
336
Iterator declaration using function output
337
"""
338
```
339
340
#### Usage Examples
341
342
```python
343
from factory.helpers import (
344
lazy_attribute, sequence, lazy_attribute_sequence,
345
container_attribute, post_generation, iterator
346
)
347
348
# Functional approach to factory definitions
349
@lazy_attribute
350
def full_name(obj):
351
return f'{obj.first_name} {obj.last_name}'
352
353
@sequence
354
def username(n):
355
return f'user_{n:04d}'
356
357
@lazy_attribute_sequence
358
def email(obj, n):
359
return f'{obj.username}_{n}@example.com'
360
361
@container_attribute
362
def parent_id(obj, containers):
363
return containers[0].id if containers else None
364
365
@post_generation
366
def setup_profile(obj, create, extracted, **kwargs):
367
if create:
368
obj.create_profile()
369
obj.send_welcome_email()
370
371
@iterator
372
def department_generator():
373
departments = ['Engineering', 'Sales', 'Marketing', 'HR']
374
while True:
375
for dept in departments:
376
yield dept
377
378
# Use in factory definition
379
class UserFactory(Factory):
380
class Meta:
381
model = User
382
383
first_name = factory.Faker('first_name')
384
last_name = factory.Faker('last_name')
385
full_name = full_name
386
username = username
387
email = email
388
department = department_generator
389
setup_profile = setup_profile
390
391
# Inline usage
392
class EmployeeFactory(Factory):
393
class Meta:
394
model = Employee
395
396
# Direct decorator usage
397
employee_id = sequence(lambda n: f'EMP{n:06d}')
398
399
display_name = lazy_attribute(
400
lambda obj: f'{obj.last_name}, {obj.first_name}'
401
)
402
403
notify_hr = post_generation(
404
lambda obj, create, extracted:
405
hr_system.notify_new_employee(obj) if create else None
406
)
407
```
408
409
### Advanced Helper Patterns
410
411
#### Custom Factory Creation
412
413
```python
414
def make_factory_with_traits(klass, traits=None, **defaults):
415
"""Custom factory creation with trait support."""
416
417
class DynamicFactory(Factory):
418
class Meta:
419
model = klass
420
421
class Params:
422
pass
423
424
# Add default attributes
425
for key, value in defaults.items():
426
setattr(DynamicFactory, key, value)
427
428
# Add traits
429
if traits:
430
for trait_name, trait_attrs in traits.items():
431
setattr(DynamicFactory.Params, trait_name, Trait(**trait_attrs))
432
433
return DynamicFactory
434
435
# Usage
436
UserFactory = make_factory_with_traits(
437
User,
438
traits={
439
'admin': {'is_staff': True, 'is_superuser': True},
440
'inactive': {'is_active': False, 'last_login': None}
441
},
442
username=sequence(lambda n: f'user{n}'),
443
email=lazy_attribute(lambda obj: f'{obj.username}@example.com')
444
)
445
446
admin_user = UserFactory(admin=True)
447
inactive_user = UserFactory(inactive=True)
448
```
449
450
#### Conditional Factory Creation
451
452
```python
453
from factory.helpers import create, build
454
455
def create_user_conditionally(persist=True, **kwargs):
456
"""Create user with conditional persistence."""
457
if persist:
458
return create(User, **kwargs)
459
else:
460
return build(User, **kwargs)
461
462
# Usage in tests
463
def test_user_creation():
464
# Development mode - don't persist
465
user = create_user_conditionally(
466
persist=settings.DEBUG,
467
name='Test User'
468
)
469
```
470
471
#### Debug-Enabled Factory Creation
472
473
```python
474
def debug_factory(factory_class):
475
"""Decorator to add debugging to factory class."""
476
477
original_create = factory_class.create
478
original_build = factory_class.build
479
480
@classmethod
481
def debug_create(cls, **kwargs):
482
with debug():
483
return original_create(**kwargs)
484
485
@classmethod
486
def debug_build(cls, **kwargs):
487
with debug():
488
return original_build(**kwargs)
489
490
factory_class.create = debug_create
491
factory_class.build = debug_build
492
493
return factory_class
494
495
# Usage
496
@debug_factory
497
class UserFactory(Factory):
498
class Meta:
499
model = User
500
501
name = Faker('name')
502
503
# All creation operations are now automatically debugged
504
user = UserFactory.create() # Debug output included
505
```