【问题标题】:Choosing from a list of names using factory boy integrated with faker使用与 faker 集成的 factory boy 从名称列表中进行选择
【发布时间】:2020-10-24 16:39:07
【问题描述】:

我正在尝试使用 factory.faker 从四个公司的列表中随机选择,并将它们用作生成名称列表的流量来源。我正在使用以下代码:

    from django.db import models
    import factory
    import factory.django
    from datetime import datetime
    from django.core.validators import MinValueValidator, MaxValueValidator
    from faker import Faker
    from faker.providers import BaseProvider
    import random

    fake = Faker()

    class User(models.Model):
        name = models.CharField(max_length=64)
        address = models.CharField(max_length=128)
        phone_number = models.CharField(max_length=32)
        login_date = models.DateTimeField(default=datetime.now(), blank=True)
        session_duration = models.IntegerField(default = 0, validators=  [
                           MinValueValidator(0),
                           MaxValueValidator(5)
                           ])
        traffic_source = models.CharField(max_length=32)

    class UserFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = User

        name = factory.Faker('name')
        address = factory.Faker('address')
        phone_number = factory.Faker('phone_number')
        login_date = factory.Faker('date')
        session_duration = factory.Faker('random_int')



        traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])

问题在于,对于所有 200 次迭代,我在 python shell 中使用以下内容:

    for _ in range(200): 
        UserFactory.create()

我的每个名字都使用同一家公司,即所有 200 个名字都使用“XYZ”。

我错过了什么吗?我想为 200 次迭代中的每一次找到一家不同的公司。任何帮助深表感谢。谢谢!

【问题讨论】:

    标签: django-rest-framework faker factory-boy


    【解决方案1】:

    这来自 Python 的解析规则。

    为什么?

    当你写这个时:

    class UserFactory(factory.django.DjangoModelFactory):
        ...
        traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
    

    Python 将执行以下步骤:

    1. 读取类声明体;
    2. 到达线traffic_source = random.choice(['XYZ', 'ABC', '123', '456']);
    3. 评估对random.choice 的调用,这可能会返回'ABC'
    4. 读取类主体的每一行(并评估其函数调用)后,创建类:
      UserFactory = type(
          name='UserFactory',
          bases=[factory.django.DjangoModelFactory],
          {'traffic_source': 'ABC', ...},
       )```
      
      

    如您所见,在解析类声明时,对random.choice 的调用仅执行一次

    这基本上是所有 factory.XXX 声明的原因:它们生成的对象仅在从工厂构建实例时才会执行其特定规则。

    那么,你应该怎么做?

    在这里,你应该使用:

    class UserFactory(factory.django.DjangoModelFactory):
        ...
        traffic_source = factory.Faker('random_choices', elements=['XYZ', 'ABC', '123', '456'])
        alt_traffic_source = factory.fuzzy.FuzzyChoice(['XYZ', 'ABC', '123', '456'])
    

    factory.Faker('random_choices')factory.fuzzy.FuzzyChoices 的主要区别在于factory.fuzzy.FuzzyChoices 支持惰性求值生成器;如果您想从查询集中进行选择,这很有用:

    • factory.Faker('random_choices', elements=Company.objects.all()) 将在导入时执行数据库查询;
    • factory.fuzzy.FuzzyChoice(Company.objects.all()) 只会在第一次调用 UserFactory.create() 时查询数据库。

    【讨论】:

    • 太棒了,是的,我的一个简单错误。我最终使用了fuzzychoice 方法,并且效果很好。感谢您的帮助!
    【解决方案2】:

    虽然不是真正随机的,但您在从一组预先存在的记录中选择时寻找的效果也可以通过使用 FactoryBoy 的 Iterator 来实现,它也可以与 QuerySet 一起使用。例如,在这里我希望每个对象都由不同于现有假用户集的人创建:

    from django.contrib.auth import get_user_model
    ...
    
    # Then, within a factory class, for one of the fields:
    created_by = factory.Iterator(get_user_model().objects.all())
    

    【讨论】:

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