django-rest-framework - 使用与 faker 集成的 factory boy 从名称列表中进行选择
问题描述
我正在尝试使用 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 次迭代中的每一次找到一家不同的公司。任何帮助深表感谢。谢谢!
解决方案
这来自 Python 的解析规则。
为什么?
当你写这个:
class UserFactory(factory.django.DjangoModelFactory):
...
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
Python 将执行以下步骤:
- 阅读类声明体;
- 到达线
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
; - 评估对 的调用
random.choice
,它可能会返回'ABC'
; - 读取类主体的每一行(并评估其函数调用)后,创建类:
UserFactory = type( name='UserFactory', bases=[factory.django.DjangoModelFactory], {'traffic_source': 'ABC', ...}, )```
如您所见,在解析类声明时,调用random.choice
只执行一次。
基本上,这就是所有factory.XXX
声明的原因:它们产生的对象只会在从工厂构建实例时执行其特定规则。
那你该怎么办?
在这里,您应该使用:
- 要么
factory.Faker
使用Faker 的random_choices
提供者; - 或者
factory.fuzzy.FuzzyChoice
:
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()
调用时查询数据库。
推荐阅读
- r - 无法访问 docker 容器中的闪亮服务器
- php - 无法打印 smalldate 值
- java - 更改窗格中较小 JPanel 的颜色
- c# - 在安装 SpecRun.SpecFlow.2-3-0 的 Visual Studio 2017 中安装 Specflow 和 Excel 时遇到问题
- android - 将 Coroutine 调用放在 Repository 或 ViewModel 中哪个更好?
- python - 在使用详细视图和覆盖 get_context_data 时优化 django 查询以避免重复
- sql - 在while循环中更新表行
- php - SPA 中的 Laravel 5.8 和 VueJS2 身份验证
- php - 在composer.json的所需依赖项中搜索实现某个接口的类
- c - 在c中将结构数组添加到文件中