gpt4 book ai didi

Python:Factory Boy 生成对象创建时指定的长度列表

转载 作者:行者123 更新时间:2023-12-04 17:31:54 28 4
gpt4 key购买 nike

我正在尝试使用 Factoryboy 在创建时指定长度的对象中创建列表。

我可以创建列表,但是由于提供的长度/大小的惰性,每次尝试创建具有指定长度的列表都会导致问题。

这是我到目前为止:

class FooFactory(factory.Factory):

class Meta:
model = command.Foo

foo_uuid = factory.Faker("uuid4")
bars = factory.List([
factory.LazyAttribute(lambda o: BarFactory()
for _ in range(3))
])

这将创建一个包含 3 个随机条的列表。我尝试使用 Params 和 exclude 的组合,但是因为 range 需要一个 Int,并且直到稍后才会延迟加载该 int,所以它会导致错误。

我想要类似于如何使用 post_generation 生成一对多关系的东西,即。
foo = FooFactory(number_of_bars=5)

有没有人有这方面的运气?

最佳答案

主要解决方案
为此需要做两件事:
parameters
LazyAttribute
(链接指向他们的文档,了解更多详情)。
参数就像工厂属性,不会传递给将要创建的实例。
在这种情况下,它们提供了一种参数化 Bar 列表长度的方法。 s。
但是为了在工厂中使用参数自定义字段,我们需要访问self ,
也就是说,正在构建的实例。
我们可以通过 LazyAttribute 实现这一点,这是一个带有一个参数的函数的声明:
正在构建的对象。
正是我们所需要的。
所以问题中的片段可以重写如下:

class FooFactory(factory.Factory):
class Meta:
model = command.Foo

class Params:
number_of_bars = 1

foo_uuid = factory.Faker("uuid4")
bars = factory.LazyAttribute(lambda self: [BarFactory()] * self.number_of_bars)
并像这样使用:
foo = FooFactory(number_of_bars=3)
如果 number_of_bars未提供参数,默认为 1用来。
缺点
可悲的是,我们在这里可以做的事情有一些限制。
在另一个工厂的定义中使用工厂的首选方法是通过
SubFactory .
这是首选的原因有两个:
  • 它尊重用于父工厂的构建策略
  • 它收集额外的关键字参数来自定义子工厂

  • 第一个意思是如果我们使用 SubFactory建一个 BarFooFactory并被称为 FooFactoryFooFactory.createFooFactory.build , Bar子工厂会尊重这一点并使用相同的策略。
    综上所述,构建策略只构建一个实例,
    而创建策略构建 将实例保存到正在使用的持久存储中,
    例如一个数据库,所以尊重这个选择很重要。
    docs
    更多细节。
    第二个意思是我们可以直接自定义 Bar的属性打电话时 FooFactory .
    例如:
    foo = FooFactory(bar__id=2)
    将设置 idbarfoo成为 2而不是什么 Bar subfactory 会默认生成。
    但我找不到使用 SubFactory 的方法 动态长度通过 Params .
    据我所知,在 FactoryBoy 期望 SubFactory 的上下文中,无法访问参数的值。 .
    问题是让我们访问正在构建的对象的声明总是期望返回一个最终值,
    不是以后要调用的另一个工厂。
    这意味着,在上面的例子中,如果我们改写:
    class FooFactory(factory.Factory):
    # ... rest of the factory
    bars = factory.LazyAttribute(lambda self: [factory.SubFactory(BarFactory)] * self.number_of_bars)
    然后称之为
    foo = FooFactory(number_of_bars=3)
    将导致 foo列表为 3 BarFactoryfoo.bars而不是 3 个列表 Bar s。
    并使用 SelfAttribute ,
    这是一种引用正在构建的实例的另一个属性的方法,也不起作用
    因为它不会在如下声明中的表达式的其余部分之前进行评估:
    class FooFactory(factory.Factory):
    # ... rest of the factory
    bars = factory.List([factory.SubFactory(BarFactory)] * SelfAttribute("number_of_bars"))
    这引发了 TypeError: can't multiply sequence by non-int of type 'SelfAttribute' .
    一种可能的解决方法是调用 BarFactory事先并传递给 FooFactory :
    number_of_bars = 3
    bars = BarFactory.create_batch(number_of_bars)
    foo = FooFactory(bars=bars)
    但这肯定没有那么好。
    我最近发现的另一个是 RelatedFactoryList .
    但这仍然是实验性的,它似乎没有办法访问参数。
    此外,由于它是生成的 基础工厂,如果实例构造函数也可能不起作用
    期望该属性作为参数。

    关于Python:Factory Boy 生成对象创建时指定的长度列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58802176/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com