【问题标题】:Deduced attributes of a LazyAttribute using Factory Boy使用 Factory Boy 推导出 LazyAttribute 的属性
【发布时间】:2021-03-01 23:43:29
【问题描述】:

在 Django 项目中使用Factory BoyFaker,我想创建推导属性,这意味着来自Faker 的方法返回一组相互依赖的值。这些值将用于工厂类的其他属性。

示例: 来自faker.providers.geolocation_on_land method 返回一个由纬度、经度、地名、两个字母的国家代码和时区组成的元组(例如('38.70734'、'-77.02303'、'Fort Washington'、'US'、 'America/New_York')。所有值都相互依赖,因为坐标定义了地点、国家、时区等。因此,我不能对 faker.providers.latitudefaker.providers.longitude 等(惰性)属性使用单独的函数。

是否有可能以某种方式访问​​惰性属性的返回值以将它们用于其他推导属性?有没有更好的方法来访问来自location_on_land 的返回值以在其他依赖属性上使用它们 我的工厂类看起来像这样:

# factory_models.py

class OriginFactory(factory.django.DjangoModelFactory):
    """Factory for Origin."""

    class Meta:
        model = models.Origin
        exclude = [
            "geo_data",
        ]
    
    # not working since not a lazy attribute
    # lat, lon, place, iso_3166_alpha_2, _ = fake.location_on_land()

    # desired outcome (not working)
    geo_data = factory.Faker("location_on_land")

    # attributes using the return values of `location_on_land` from lazy attribute (pseudo-code, desired)
    latitude = geo_data[...][0]
    longitude = geo_data[...][1]
    # foreign key
    iso_3166_alpha_2 = models.Country.objects.get(iso_3166_alpha_2=geo_data[...][2])
    ...
# models.py

class Origin(models.Model):
    origin_id = models.AutoField(
        primary_key=True,
        db_column="origin_id",
    )

    latitude = models.FloatField(
        null=True,
        db_column="latitude",
    )

    longitude = models.FloatField(
        null=True,
        db_column="longitude",
    )

    region = models.CharField(
        max_length=100,
        blank=True,
        db_column="region",
    )

    iso_3166_alpha_2 = models.ForeignKey(
        to=Country,
        on_delete=models.PROTECT,
        db_column="iso_3166_alpha_2",
    ...
    )

【问题讨论】:

    标签: python django faker factory-boy


    【解决方案1】:

    使用factory.Params 时,factory.LazyAttribute 的第一个参数上可用的结果属性:传入的实例是一个存根,用于为实际模型调用构建参数。

    在你的情况下,我会选择以下工厂。

    注意geo_data 字段被声明为参数(即不传递给models.Origin 构造函数);但它仍然可用于工厂的其他声明。

    class OriginFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = models.Origin
    
        class Params:
            geo_data = factory.Faker('location_on_land')
    
        latitude = factory.LazyAttribute(lambda o: o.geo_data[0])
        longitude = factory.LazyAttribute(lambda o: o.geo_data[1])
        iso_3166_alpha_2 = factory.LazyAttribute(
            lambda o: models.Country.objects.get(iso_3166_alpha_2=o.geo_data[3])
        )
    

    【讨论】:

    • 非常感谢,我已经搜索了几个小时才能找到解决方案!我对 Factory Boy 还很陌生,因此我根本不知道 Params 类。
    猜你喜欢
    • 2020-05-03
    • 2018-02-06
    • 1970-01-01
    • 2015-12-26
    • 1970-01-01
    • 2015-05-02
    • 2019-11-05
    • 2020-07-12
    • 2020-04-09
    相关资源
    最近更新 更多