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

1

13

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?

Antlion answered 7/9, 2017 at 15:19 Comment(4)
What are the fields on your models.Person class? This is relevant info.Aixlachapelle
OK, I wasn't sure it would help, but I've added it now.Antlion
@PhilGyford: Does this work? You'd have to create a prefix and a name class attribute that don't exist in your model and then combine them to create full_name. I'm not sure if this will cause an error, as your original Person model doesn't have those fields.Microfilm
@Microfilm Thanks, but I tried that, and did get an error for the reason you suggest.Antlion
M
21

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.

Microfilm answered 7/9, 2017 at 16:42 Comment(2)
Thanks! I thought maybe there was a way with factory.LazyAttribute but never managed to find quite the right combination of fakes.Antlion
Pretty good. Only quibble is that you will generate transgender (in the literal sense of the word) names this way.Aixlachapelle

© 2022 - 2024 — McMap. All rights reserved.