【问题标题】:Can not create multiple instance of Model using Factory Boy and Faker无法使用 Factory Boy 和 Faker 创建多个模型实例
【发布时间】:2021-08-23 20:48:03
【问题描述】:

我正在尝试使用 django-factory-boy 和 faker 创建多个 django 模型实例。但是我需要批量创建实例(不是单个)。但是我不能使两个属性都对应(货币的codename)。

我有一个 django 模型:

class Currency(models.Model):
    """Currency model"""
    name = models.CharField(max_length=120, null=False,
                            blank=False, unique=True)
    code = models.CharField(max_length=3, null=False, blank=False, unique=True)
    symbol = models.CharField(max_length=5, null=False,
                              blank=False, default='$')

    def __str__(self) -> str:
        return self.code

我有一家工厂

import factory
from apps.Payment.models import Transaction, Currency
from faker import Faker
fake = Faker()


class CurrencyFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Currency

    # code and name get assigned when the class is called hence if we use
    # create_batch(n) we get all n object same
 
    # code, name = fake.currency() 

    code = factory.LazyAttribute(lambda _: fake.currency()[0]) 
    name = factory.LazyAttribute(lambda _: fake.currency()[1]) 
    symbol = '$'

我面临的问题是codename 得到不同的值并且不匹配。看看faker 返回什么。

>>> from faker import Faker
>>> fake = Faker()
>>> fake.currency()
('JPY', 'Japanese yen') 

查看货币名称与货币代码不对应。我还需要使用CurrencyFactory.create_batch(5) 创建至少 5 到 6 个对象。

# mismatch in code and name
NAME                            CODE

Netherlands Antillean guilder   ZAR
Western Krahn language          UGX
Colombian peso                  KHR

我想要什么

NAME                            CODE

Indian National Rupee           INR
Japanese yen                    JPY

【问题讨论】:

    标签: python django integration-testing faker factory-boy


    【解决方案1】:

    最好的方法是通过class Params:

    class CurrencyFactory(factory.model.DjangoModelFactory):
      class Meta:
        model = Currency
      class Params:
        currency = factory.Faker("currency")  # (code, name)
    
      code = factory.LazyAttribute(lambda o: o.currency[0])
      name = factory.LazyAttribute(lambda o: o.currency[1])
    

    想法是:

    • 工厂调用一次Faker,生成currency = (code, name)参数;
    • 然后它将该参数的组件映射到模型的正确字段
    • 由于currency 被声明为参数,它不会被传递给模型(它会自动添加到Meta.exclude

    【讨论】:

      猜你喜欢
      • 2020-04-09
      • 2018-02-16
      • 2019-12-22
      • 2021-10-04
      • 2017-12-17
      • 2018-05-08
      • 2019-03-31
      • 2017-04-23
      • 1970-01-01
      相关资源
      最近更新 更多