Search code examples
pythondjangoclass-methodfactory-boy

How to pass in a starting sequence number to a Django factory_boy factory?


factory_boy defaults to 1 for sequences. How can I pass in a number to use as a different starting number instead? I can subclass the _setup_next_sequence() method, but how can I give it a variable to use?

# File: models.py
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)


# File: factories.py
from .models import Book
import factory

class BookFactory(factory.Factory):
  FACTORY_FOR = BookModel  
  title = factory.Sequence(lambda n: u'Title #{}'.format(n))

  @classmethod
  def _setup_next_sequence(cls):      
      # Instead of defaulting to starting with number 1, start with starting_seq_num.
      # But how do I set starting_seq_num?
      return starting_seq_num


# File: make_data.py
from factories import BookFactory

# somehow set starting sequence number here?

BookFactory().create()

I'm using factory_boy 1.2.0 (via pip install factory_boy)
factory_boy code: https://github.com/dnerdy/factory_boy


Solution

  • I found two ways of solving this:

    1. Use a module variable
    2. Use a class attribute set outside of the class definition

    Use a module variable:

    # File: factories.py
    from .models import Book
    import factory
    
    starting_seq_num = 0
    
    class BookFactory(factory.Factory):
      FACTORY_FOR = BookModel  
      title = factory.Sequence(lambda n: u'Title #{}'.format(n))
    
      @classmethod
      def _setup_next_sequence(cls):      
          # Instead of defaulting to starting with 0, start with starting_seq_num.
          return starting_seq_num
    
    # File: make_data.py
    import factories
    
    factories.starting_seq_num = 100    
    factories.BookFactory().create()
    

    Use a class attribute set outside of the class definition:

    # File: factories.py
    from .models import Book
    import factory
    
    class BookFactory(factory.Factory):
      # Note that starting_seq_num cannot be set here in the class definition,
      # because Factory will then pass it as a kwarg to the model's create() method
      # and cause an exception.  It must be set outside the class definition.
      FACTORY_FOR = BookModel  
      title = factory.Sequence(lambda n: u'Title #{}'.format(n))
    
      @classmethod
      def _setup_next_sequence(cls):      
          return getattr(cls, 'starting_seq_num', 0)
    
    # File: make_data.py
    from factories import BookFactory
    
    BookFactory.starting_seq_num = 100
    BookFactory().create()