如何为Django的factory_boy工厂传入起始序列号?

16 投票
4 回答
7805 浏览
提问于 2025-04-17 19:02

factory_boy 默认的序列号是 1。我想知道怎么才能传入一个数字,来作为不同的起始序列号呢?我可以重写 _setup_next_sequence() 这个方法,但我该如何给它一个变量来使用呢?

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

我正在使用 factory_boy 1.2.0(通过 pip install factory_boy 安装)
factory_boy 的代码可以在这里找到: https://github.com/dnerdy/factory_boy

4 个回答

6

更新:factory_boy 现在可以处理这个问题了!

在最新版本的 factory_boy(截至今天是 2.8.1)中,现在可以强制设置序列计数器为一个指定的值:

按调用强制设置值

为了在特定的 Factory 实例化时强制设置计数器,只需在参数中传入 __sequence=42 的值:

class AccountFactory(factory.Factory):
        class Meta:
            model = Account
        uid = factory.Sequence(lambda n: n)
        name = "Test"

然后在控制台中:

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

同时也可以将计数器重置为一个特定的值:

>>> AccountFactory.reset_sequence(42)
>>> AccountFactory().uid
42
>>> AccountFactory().uid
43
10

除了Rob Bednark的回答之外,

我们可以使用reset_sequence()这个函数,它可以重置计数器到一个特定的值

# File: make_data.py
import factories

factories.BookFactory.reset_sequence(100)
my_book = factories.BookFactory().create()
print(my_book.title) # Title #100
6

我找到了两种解决这个问题的方法:

  1. 使用模块变量
  2. 在类定义外设置类属性

使用模块变量:

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

在类定义外设置类属性:

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

撰写回答