Как в Factory Boy соединить строки, созданные с помощью Faker?

Я хочу использовать Factory Boy и его поддержка для Faker для создания строк от более чем одного поставщика. например объединение prefix и 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'))

Но это, кажется, не работает. например.:

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

Что мне не хватает?


person Phil Gyford    schedule 07.09.2017    source источник
comment
Какие поля есть в вашем классе models.Person? Это актуальная информация.   -  person wim    schedule 07.09.2017
comment
Хорошо, я не был уверен, что это поможет, но я добавил это сейчас.   -  person Phil Gyford    schedule 07.09.2017
comment
@PhilGyford: работает ли это? Вам нужно будет создать атрибут класса prefix и name, которых нет в вашей модели, а затем объединить их для создания full_name. Я не уверен, что это вызовет ошибку, так как ваша исходная модель Person не имеет этих полей.   -  person Blender    schedule 07.09.2017
comment
@Blender Спасибо, но я попробовал это и получил ошибку по той причине, которую вы предлагаете.   -  person Phil Gyford    schedule 07.09.2017


Ответы (1)


Вы можете использовать (по сути, недокументированный) атрибут exclude, чтобы ваш первый подход работал:

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))

Вы также можете просто использовать factory.LazyAttribute и сгенерировать все сразу, напрямую используя 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()))

Недостатком этого подхода является то, что у вас нет простого доступа к префиксу или имени человека.

person Blender    schedule 07.09.2017
comment
Спасибо! Я думал, может быть, есть способ с factory.LazyAttribute, но так и не смог найти подходящую комбинацию подделок. - person Phil Gyford; 07.09.2017
comment
Вполне нормально. Придираюсь только к тому, что таким образом вы будете генерировать трансгендерные (в прямом смысле этого слова) имена. - person wim; 07.09.2017