当Django模型中的字段具有选项选项时,请参阅Django choices field option,它使用包含2个项的可迭代的迭代来定义允许的值。例如:
模型
class IceCreamProduct(models.Model):
PRODUCT_TYPES = (
(0, 'Soft Ice Cream'),
(1, 'Hard Ice Cream'),
(2, 'Light Ice Cream'),
(3, 'French Ice Cream'),
(4, 'Italian-style Gelato'),
(5, 'Frozen Dairy Dessert'),
)
type = models.PositiveSmallIntegerField('Type', choices=PRODUCT_TYPES, default=0)
要在Factory Boy中生成随机值以供选择,我会使用factory.fuzzy.FuzzyChoice,但这只选择2个项目的可迭代。它不能采用所选迭代的第一项。例如:
工厂
class IceCreamProductFactory(factory.django.DjangoModelFactory):
class Meta:
model = IceCreamProduct
type = factory.fuzzy.FuzzyChoice(IceCreamProduct.PRODUCT_TYPES)
错误的
TypeError: int() argument must be a string, a bytes-like object or a number, not 'tuple'
获取元组的第一项是不可能的。例如:
工厂
class IceCreamProductFactory(factory.django.DjangoModelFactory):
class Meta:
model = IceCreamProduct
type = factory.fuzzy.FuzzyChoice(IceCreamProduct.PRODUCT_TYPES)[0]
错误的
TypeError: 'FuzzyChoice' object does not support indexing
可以使用默认的Python随机迭代器,但这会在声明时生成一个值,因此每个工厂对象都具有相同的随机值。例如:
工厂
class IceCreamProductFactory(factory.django.DjangoModelFactory):
class Meta:
model = IceCreamProduct
type = random.choice(IceCreamProduct.PRODUCT_TYPES)][0]
如何在Factory Boy中解决这个问题?我是否需要创建自定义FuzzyAttribute? (如果是,请举个例子)
答案 0 :(得分:10)
您不需要FuzzyAttribute。
您可以限制可能的值,只需通过执行以下操作,将每种产品类型的int值赋予FuzzyChoice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "conio.h"
int main()
{
char ch;
char buffer[100];
char* p;
p = buffer;
FILE *fp;
fp = fopen("D:\\Telenor_Short_01.vts","rb");// binary mode
fseek(fp,0,SEEK_END); //sets the file position of the stream to the given offset
int size=ftell(fp); //returns the current file position of the given stream.
printf("size of file is :%d\n",size);
if( fp == NULL ) //error checking
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
fread(p,1,100,fp);
for (int i=0;i<100;i++)
{
printf("%04x\n",*p);
p++;
}
fclose(fp);
/*printf("The contents of %s file are :\n", file_name);*/
/*int i;
while( ( ch = fgetc(fp) ) != EOF )
{
printf("%02X ",ch);
if( !(++i % 16) ) putc('\n', stdout);
}
fclose(fp);
putc('\n', stdout);*/
_getch();
return 0;
}
它应该做的工作。
请注意,模糊模块最近已被弃用,请参阅(https://factoryboy.readthedocs.org/en/latest/fuzzy.html),您可能想要使用LazyFunction。
答案 1 :(得分:6)
以下是lothiraldan建议使用factory.LazyFunction
进行此操作的方法:
import random
...
def get_license_type():
"Return a random license type from available choices."
lt_choices = [x[0] for x in choices.LICENSE_TYPE_CHOICES]
return random.choice(lt_choices)
def get_line_type():
"Return a random line type from available choices."
lt_choices = [x[0] for x in choices.LINE_TYPE_CHOICES]
return random.choice(lt_choices)
class ProductFactory(ModelFactory):
name = factory.Faker('name')
description = factory.Faker('text')
license_type = factory.LazyFunction(get_license_type)
line_type = factory.LazyFunction(get_line_type)
class Meta:
model = 'products.ProductBaseV2'
答案 2 :(得分:4)
你可以像这样轻松地完成
class IceCreamProductFactory(factory.django.DjangoModelFactory):
type = factory.Faker(
'random_element', elements=[x[0] for x in IceCreamProduct.PRODUCT_TYPES]
)
class Meta:
model = IceCreamProduct
PS。不要将type
用作属性
答案 3 :(得分:3)
因为我必须为很多模型做到这一点,所以我想出了一个更抽象的erichonkanen解决方案版本。我定义了一个帮助器类,我将它放在项目的顶级测试目录中,并将其导入包含工厂的模块中:
test/helpers.py
import factory
import random
class ModelFieldLazyChoice(factory.LazyFunction):
def __init__(self, model_class, field, *args, **kwargs):
choices = [choice[0] for choice in model_class._meta.get_field(field).choices]
super(ModelFieldLazyChoice, self).__init__(
function=lambda: random.choice(choices),
*args, **kwargs
)
并在app/factories.py
from app.models import IceCreamProduct
from test.helpers import ModelFieldLazyChoice
class IceCreamProductFactory(factory.django.DjangoModelFactory):
class Meta:
model = IceCreamProduct
type = ModelFieldLazyChoice(IceCreamProduct, 'type')