简体   繁体   English

Factory_boy 不创建不同的用户对象 Django

[英]Factory_boy not creating different User objects Django

I am new to Factory_boy with Django. After spending some time I understood how to create a factory for User model.我是 Django 的 Factory_boy 新手。花了一些时间后,我了解了如何为用户 model 创建工厂。

I am using the default user model and following is my factory.我使用默认用户 model 以下是我的工厂。 I am using Faker for randomness我使用 Faker 来实现随机性

import factory
from . import models
from django.contrib.auth.models import User
from faker import Faker
from django.contrib.auth.hashers import make_password

fake = Faker()

class UserFactory(factory.DjangoModelFactory):
    class Meta:
        model = User
        django_get_or_create = ('email',)

    first_name = fake.first_name()
    last_name = fake.last_name()
    email = first_name+"."+last_name+"@gmail.com"
    password = make_password("ojasojas")
    username = first_name+"_"+last_name

Now in the django shell现在在 django shell

I use UserFactory.create() to crate an user.我使用 UserFactory.create() 来创建一个用户。 this works fine.这很好用。 Is it possible to loop through create statement and crate 5 different users?是否可以循环创建语句并创建 5 个不同的用户? Now when I am doing that I am getting only one user (crated once and 'get' 4 times) as follows.现在,当我这样做时,我只获得了一个用户(装箱一次并“获得”4 次),如下所示。 What am I missing?我错过了什么? 在此处输入图像描述

You are defining class attributes for your factory, which get evaluated only when the class is defined.您正在为您的工厂定义 class 属性,只有在定义 class 时才会评估这些属性。 email = first_name+"."+last_name+"@gmail.com" will be evaluated once, not each time you call UserFactory.create() , hence the unique constraint errors. email = first_name+"."+last_name+"@gmail.com"将被评估一次,而不是每次调用UserFactory.create()时,因此唯一约束错误。 The usual solution to this is to instead define instance attributes via __init__() , but FactoryBoy has their own solution to this: lazy attributes .通常的解决方案是通过__init__()定义实例属性,但 FactoryBoy 对此有自己的解决方案:惰性属性

This may not be the best solution, but its a work around I've been using lately.这可能不是最好的解决方案,但它是我最近一直在使用的解决方法。 I set the following Global:我设置了以下全局:

NAMES = [factory.Faker('name')._get_faker().name() for i in range(5)]

In this case, the above will generate a list of 5 fake names.在这种情况下,上面将生成一个包含 5 个假名的列表。

NOTE: this does not guarantee a unique name (as FuzzyChoice will just select one from the list).注意:这不保证唯一的名称(因为FuzzyChoice只会从列表中选出一个 select)。

and within your factory:在您的工厂内:

name = factory.LazyAttribute(lambda obj: factory.fuzzy.FuzzyChoice(NAMES).fuzz()) 

FactoryBoy offers LazyFunction and LazyAttribute classes to achieve this. FactoryBoy 提供了LazyFunctionLazyAttribute类来实现这一点。 Difference between them is that you can access other model-factory fields in LazyAttribute .它们之间的区别在于您可以访问LazyAttribute中的其他模型工厂字段。

Here is an example:这是一个例子:

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = models.User
        django_get_or_create = ('email',)
    
    @staticmethod
    def gen_email(x):
        return x.first_name + "." + x.last_name + "@gmail.com"
    
    first_name = factory.LazyFunction(fake.first_name)
    last_name = factory.LazyFunction(fake.last_name)
    email = factory.LazyAttribute(gen_email)
    password = make_password("ojasojas")
    username = factory.LazyAttribute(lambda x: x.first_name + "_" + x.last_name)

You can use lambda expressions as I've used here for demonstration in making the username field 'lazy-evaluated', or create functions (static method) and pass them to LazyFunction / LazyAttribute .您可以使用lambda表达式,正如我在此处用于使用username字段“延迟评估”的演示,或创建函数(静态方法)并将它们传递给LazyFunction / LazyAttribute


You can read more about these classes in official documentation of Factory Boy:您可以在 Factory Boy 的官方文档中阅读有关这些类的更多信息:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM