在dict中使用Factory Boy在Django中创建数据模型工厂?或者,让FactoryBoy按需评估子工厂?

时间:2020-09-29 15:06:45

标签: django factory-boy

我有以下ModelFactory:

class ProjectDataModelFactory(DjangoModelFactory):
    project = factory.SubFactory("projects.factories.ProjectModelFactory")
    version = "1"
    content = {
        "id": {"value": fuzzy.FuzzyText(length=7, chars=string.ascii_letters).fuzz().upper(), "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",
        },
    } 

content["id"]中,我希望value成为project.external_id而不是fuzzy.FuzzyText(length=7, chars=string.ascii_letters).fuzz().upper(). external_idProjectModel.的一部分,但是当我将project.external_id放在模糊器的位置,会出现此错误:

AttributeError:'SubFactory'对象没有属性'external_id

这似乎仅是字典问题。在其他情况下使用它时,我们没有遇到任何问题。

我没有太多使用FactoryBoy的经验,因此很容易变得微不足道。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您遇到的第一个问题是:导入类后,将评估您在random字典中对.fuzz()content的所有调用:每个实例将使用完全相同的值。

为了执行延迟评估,必须将它们包装在factory_boy提供的声明中:

class ProjectDataModelFactory(DjangoModelFactory):
    project = factory.SubFactory("projects.factories.ProjectModelFactory")
    version = "1"
    content = factory.Dict(
        id=factory.Dict(
            value=fuzzy.FuzzyText(length=7, chars=string.ascii_uppercase),
            type="string",
        ),
        win_probability=factory.Dict(
            value=fuzzy.FuzzyInteger(0, 100),
            type="number",
        ),
        bid_value=factory.Dict(
            value=fuzzy.FuzzyInteger(0, 10_000_000),
            type="number",
        ),
        status=factory.Dict(
            value=fuzzy.FuzzyChoice(["Won", "Lost"]),
            type="string",
        ),
        sector=factory.Dict(
            value=fuzzy.FuzzyChoice(
                ["Construction", "Technology", "Finance", "Consulting", "Agriculture", "Engineering"],
            ),
            type="string",
        ),
    )

factory.Dict(**kwargs)基本上是factory.SubFactory(DictFactory, **kwargs)的别名;然后,您可以像使用简单的SubFactory一样使用任何声明。

对于您的最初目标,现在可以轻松使用所有功能:

class ProjectDataModelFactory(DjangoModelFactory):
    project = factory.SubFactory("projects.factories.ProjectModelFactory")
    version = "1"
    content = factory.Dict(
        id=factory.Dict(
            # . is the {"value": x, "type": "string"} dict;
            # .. is {"id": {"value": x, ...}} dict;
            # ... is the ProjectData(content={"id": {...}}) object.
            value=factory.SelfAttribute('...project.external_id'),
            type="string",
        ),
        # Other fields here
    )