6π
I found two ways of solving this:
- Use a module variable
- 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()
10π
In addition to the answer of Rob Bednark
We can use reset_sequence()
function, which will reset the counter to a specific value.
# File: make_data.py
import factories
factories.BookFactory.reset_sequence(100)
my_book = factories.BookFactory().create()
print(my_book.title) # Title #100
- In django, is aggregate(Count()) faster or better than .count() in anyway?
- How to set timeout for database connection in django
- How do I use Django signals with an abstract model?
- Django: Faking a field in the admin interface?
- How does django-nose differ from the default Django test-runner
6π
Update: factory_boy
now handles it!
In the latest version of factory_boy
(2.8.1
to this day) it is now possible to force the sequence counter into a define value:
Forcing the value on a per-call basis
In order to force the counter for a specific
Factory
instantiation, just pass the value in the
__sequence=42
parameter:
class AccountFactory(factory.Factory):
class Meta:
model = Account
uid = factory.Sequence(lambda n: n)
name = "Test"
Then in the console:
>>> obj1 = AccountFactory(name="John Doe", __sequence=10)
>>> obj1.uid # Taken from the __sequence counter
10
>>> obj2 = AccountFactory(name="Jane Doe")
>>> obj2.uid # The base sequence counter hasn't changed
1
And it is also possible to reset the counter to a specific value:
>>> AccountFactory.reset_sequence(42)
>>> AccountFactory().uid
42
>>> AccountFactory().uid
43
1π
The third, and simplest way:
# File: factories.py
from .models import BookModel
import factory
class BookFactory(factory.Factory, starting_seq_num):
FACTORY_FOR = BookModel
title = factory.Sequence(lambda n: u'Title #{}'.format(n + starting_seq_num))
# File: make_data.py
import factories
book = factories.BookFactory(512).create() #Start with 512
Iβm only starting with Factory Boy myself, and not too experienced in Python either, so I may be missing something, but you see where Iβm going here. To make it clearer, I think Iβd actually prefer it to be keyworded:
class BookFactory(factory.Factory, title_seq_start=-1):
...
book = factories.BookFactory(title_seq_start=512).create()