File tree Expand file tree Collapse file tree 3 files changed +123
-0
lines changed Expand file tree Collapse file tree 3 files changed +123
-0
lines changed Original file line number Diff line number Diff line change 1+ from dataclasses import dataclass
2+
3+ from polyfactory .factories import DataclassFactory
4+
5+
6+ @dataclass
7+ class Account :
8+ """User account model."""
9+
10+ username : str
11+ email : str
12+ is_verified : bool
13+ verification_token : str
14+
15+
16+ class AccountFactory (DataclassFactory [Account ]):
17+ """Factory for Account with post_build hook."""
18+
19+ @classmethod
20+ def post_build (cls , account : Account ) -> Account :
21+ """Post-build hook to modify the created instance.
22+
23+ This hook is called after the model instance is created,
24+ allowing you to run custom logic on the fully-generated object.
25+ """
26+ # Auto-verify accounts in test environment
27+ if account .username .startswith ("test_" ):
28+ account .is_verified = True
29+ account .verification_token = ""
30+
31+ return account
32+
33+
34+ def test_post_build_hook () -> None :
35+ # Regular account will have random is_verified value
36+ regular_account = AccountFactory .build (username = "john_doe" )
37+ assert regular_account .username == "john_doe"
38+
39+ # Test account will be auto-verified by the post_build hook
40+ test_account = AccountFactory .build (username = "test_user" )
41+ assert test_account .is_verified is True
42+ assert test_account .verification_token == ""
Original file line number Diff line number Diff line change 1+ from dataclasses import dataclass
2+ from typing import Any , Dict
3+
4+ from polyfactory .factories import DataclassFactory
5+
6+
7+ @dataclass
8+ class Product :
9+ """Product model."""
10+
11+ name : str
12+ price : float
13+ tax_rate : float
14+ total_price : float
15+
16+
17+ class ProductFactory (DataclassFactory [Product ]):
18+ """Factory for Product with post_generate hook."""
19+
20+ @classmethod
21+ def post_generate (cls , result : Dict [str , Any ]) -> Dict [str , Any ]:
22+ """Post-generate hook to modify kwargs before model creation.
23+
24+ This hook is called after field values are generated but before
25+ the model instance is created, allowing you to compute derived
26+ fields based on other generated values.
27+ """
28+ # Calculate total_price based on price and tax_rate
29+ price = result ["price" ]
30+ tax_rate = result ["tax_rate" ]
31+ result ["total_price" ] = price * (1 + tax_rate )
32+
33+ return result
34+
35+
36+ def test_post_generate_hook () -> None :
37+ product = ProductFactory .build ()
38+
39+ # Verify total_price was calculated correctly
40+ expected_total = product .price * (1 + product .tax_rate )
41+ assert abs (product .total_price - expected_total ) < 0.01
42+
43+ # Verify with specific values
44+ product = ProductFactory .build (price = 100.0 , tax_rate = 0.2 )
45+ assert product .total_price == 120.0
Original file line number Diff line number Diff line change @@ -164,3 +164,39 @@ forward reference names to their resolved types.
164164.. note ::
165165 The Pydantic ModelFactory has a default forward reference mapping for ``JsonValue `` to resolve to ``str ``
166166 to avoid recursive issues with Pydantic's JsonValue type.
167+
168+ Lifecycle Hooks
169+ ---------------
170+
171+ Factories provide two lifecycle hooks that allow you to customize the model creation process:
172+
173+ Post-Build Hook
174+ ^^^^^^^^^^^^^^^^
175+
176+ The :meth: `~polyfactory.factories.base.BaseFactory.post_build ` hook is called after a model instance
177+ is created. This is useful for running custom logic on the fully-generated object, such as setting up
178+ relationships, calculating derived fields, or modifying the instance based on its generated values.
179+
180+ .. literalinclude :: /examples/configuration/test_example_12.py
181+ :caption: Using the post_build hook
182+ :language: python
183+
184+ The ``post_build `` method receives the created model instance and must return it (potentially modified).
185+
186+ Post-Generate Hook
187+ ^^^^^^^^^^^^^^^^^^^
188+
189+ The :meth: `~polyfactory.factories.base.BaseFactory.post_generate ` hook is called after field values
190+ are generated but before the model instance is created. This allows you to modify the kwargs dictionary
191+ that will be passed to the model constructor, making it ideal for computing derived fields or ensuring
192+ consistency between related fields.
193+
194+ .. literalinclude :: /examples/configuration/test_example_13.py
195+ :caption: Using the post_generate hook
196+ :language: python
197+
198+ The ``post_generate `` method receives the generated kwargs dictionary and must return it (potentially modified).
199+
200+ .. note ::
201+ Both hooks are classmethods that can be overridden in your factory class. They are called automatically
202+ by ``build() ``, ``batch() ``, and all persistence methods.
You can’t perform that action at this time.
0 commit comments