Search code examples
pythonfakerfactory-boy

In Factory Boy, how to join strings created with Faker?


I want to use Factory Boy and its support for Faker to generate strings from more than one provider. e.g. combining prefix and name:

# models.py
from django.db import models

class Person(models.Model):
    full_name = models.CharField(max_length=255, blank=False, null=False)


# factories.py
import factory

class PersonFactory(factory.Factory):
    class Meta:
        model = models.Person

    full_name = '{} {}'.format(factory.Faker('prefix'), factory.Faker('name'))

But this doesn't seem to work. e.g.:

>>> person = PersonFactory()
>>> person.full_name
'<factory.faker.Faker object at 0x7f25f4b09e10> <factory.faker.Faker object at 0x7f25f4ab74d0>'

What am I missing?


Solution

  • You can use the (essentially undocumented) exclude attribute to make your first approach work:

    class PersonFactory(factory.Factory):
        class Meta:
            model = Person
            exclude = ('prefix', 'name')
    
        # Excluded
        prefix = factory.Faker('prefix')
        name = factory.Faker('name')
    
        # Shows up
        full_name = factory.LazyAttribute(lambda p: '{} {}'.format(p.prefix, p.name))
    

    You could also just use factory.LazyAttribute and generate it all in one go by directly using faker:

    from faker import Faker
    
    fake = Faker()
    
    class PersonFactory(factory.Factory):
        class Meta:
            model = Person
    
        # Shows up
        full_name = factory.LazyAttribute(lambda p: '{} {}'.format(fake.prefix(), fake.name()))
    

    The downside of this approach is that you you don't have easy access to the person's prefix or name.