Django Factory Boy loop return same value

I'm trying to generate fake objets from loop but always returns the same objet

utilities.py:

...
for _ in range(number_objects):
    try:
        element = app_factories.UserFactory()
        print(element)
    except Exception as e:
        print(e)
        print(type(e))
...

factories.py

from faker import Faker
from factory.fuzzy import FuzzyChoice
from factory.django import DjangoModelFactory

fake = Faker(['es-ES'])

class UserFactory(DjangoModelFactory):
  name = fake.name()
  email = '{}@mailcom'.format(slugify(name))
  height = fake.numerify(text='1##')
  friend = FuzzyChoice(app_models.User.objects.all())

  class Meta:
    model = app_models.User

Probably it will be from the seed or generator but I don't know how to solve it. Anybody could help me please ? Thanks in advance.

Upvotes: 2

Views: 1338

Answers (1)

Xelnor
Xelnor

Reputation: 3589

The problem is that calls to faker are evaluated at module import time.

What you've written is equivalent to:

fake = Faker(['es-ES'])
name = fake.name()  # "John Doe"
email = '{}@mailcom'.format(slugify(name))  # 'johndoe@mailcom'
height = fake.numerify(text='1##')  # 123
friend = FuzzyChoice(app_models.User.objects.all())  # Lazy

class UserFactory(DjangoModelFactory):
  ...
  name = "John Doe"
  email = 'johndoe@mailcom'
  height = 123
  friend = FuzzyChoice(app_models.User.objects.all())

Instead, use:

class UserFactory(DjangoModelFactory):
  ...
  name = factory.Faker("name")
  email = factory.LazyAttribute(lambda o: '{}@mailcom'.format(slugify(o.name)))

You'll find a more detailed explanation of the difference between your code and using FactoryBoy's helpers in my answer there: Django Tests - User Factory with create_batch

Upvotes: 4

Related Questions