Django中如何在字典内用Factory Boy关联子工厂属性?
I've run into this exact issue before with Factory Boy—let's break down what's happening and how to fix it.
Why the Error Happens
When you define the content dictionary directly in your factory class, it gets evaluated when the class is loaded, not when an instance is created. At that point, project is still a SubFactory object (not an actual Project model instance), so it doesn't have an external_id attribute. That's why you're getting the AttributeError.
Fix: Use factory.lazy_attribute
Factory Boy provides lazy_attribute to defer the creation of an attribute until the instance is being built. This way, the related project object will already exist, and you can safely access its external_id.
Here's how to modify your factory:
import factory from factory.django import DjangoModelFactory import fuzzy import random import string class ProjectDataModelFactory(DjangoModelFactory): project = factory.SubFactory("projects.factories.ProjectModelFactory") version = "1" @factory.lazy_attribute def content(self): # Now self.project is a fully instantiated Project model instance return { "id": {"value": self.project.external_id, "type": "string"}, "win_probability": {"value": fuzzy.FuzzyInteger(0, 100).fuzz(), "type": "number"}, "bid_value": { "value": fuzzy.FuzzyInteger(0, 10000000).fuzz(), "type": "number", }, "status": {"value": random.choice(["Won", "Lost"]), "type": "string"}, "sector": { "value": random.choice( ["Construction", "Technology", "Finance", "Consulting", "Agriculture", "Engineering"] ), "type": "string", }, }
Alternative: Lambda Syntax with factory.LazyAttribute
If you prefer a more concise inline approach, you can use the lambda version:
class ProjectDataModelFactory(DjangoModelFactory): project = factory.SubFactory("projects.factories.ProjectModelFactory") version = "1" content = factory.LazyAttribute(lambda obj: { "id": {"value": obj.project.external_id, "type": "string"}, "win_probability": {"value": fuzzy.FuzzyInteger(0, 100).fuzz(), "type": "number"}, "bid_value": { "value": fuzzy.FuzzyInteger(0, 10000000).fuzz(), "type": "number", }, "status": {"value": random.choice(["Won", "Lost"]), "type": "string"}, "sector": { "value": random.choice( ["Construction", "Technology", "Finance", "Consulting", "Agriculture", "Engineering"] ), "type": "string", }, })
Key Takeaway
Any time you need to reference a related model's attributes in your factory, use lazy evaluation (like lazy_attribute). This ensures that all dependent objects are fully created before you try to access their properties.
内容的提问来源于stack exchange,提问作者Matthew Gaiser

