使用 Factory Boy 推导出 LazyAttribute 的属性

Deduced attributes of a LazyAttribute using Factory Boy

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

示例: 来自 faker.providers.geo return 的 location_on_land method 是纬度、经度、地名、两个字母的国家代码和时区的元组(例如('38.70734'、'-77.02303' , 'Fort Washington', 'US', 'America/New_York')。所有的值都相互依赖,因为坐标定义了地点、国家、时区等。因此我不能为 (lazy ) 属性,例如 faker.providers.latitudefaker.providers.longitude.

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

# 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",
    ...
    )

使用factory.Params, the resulting attribute is available on the first parameter on 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])
    )