Search code examples
djangodjango-testingdjango-testsfactory-boy

factory boy: define field that depends on other field


How to define a field that depends on other field using factory-boy?

For instance, I'd like to define an email that depends on the first name and last name of an User.

I tried using the post_generation decorator. However, my system requires the definition of the email before creating the instance.


Solution

  • Use LazyAttribute:

    from the docs:

    The LazyAttribute is a simple yet extremely powerful building brick for extending a Factory.

    It takes as argument a method to call (usually a lambda); that method should accept the object being built as sole argument, and return a value.

    class UserFactory(factory.Factory):
        class Meta:
            model = User
    
        username = 'john'
        email = factory.LazyAttribute(lambda o: '%[email protected]' % o.username)
    

    or the lazy_attribute decorator.

    from the docs:

    If a simple lambda isn’t enough, you may use the lazy_attribute() decorator instead.

    This decorates an instance method that should take a single argument, self; the name of the method will be used as the name of the attribute to fill with the return value of the method:

    class UserFactory(factory.Factory)
        class Meta:
            model = User
    
        name = u"Jean"
    
        @factory.lazy_attribute
        def email(self):
            # Convert to plain ascii text
            clean_name = (unicodedata.normalize('NFKD', self.name)
                            .encode('ascii', 'ignore')
                            .decode('utf8'))
            return u'%[email protected]' % clean_name