如何将起始序列号传递给Django factory_boy工厂?

时间:2013-03-14 05:59:49

标签: python django class-method factory-boy

对于序列,

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 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:1)

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

  1. 使用模块变量
  2. 使用类定义
  3. 之外的类属性集

    使用模块变量:

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

答案 2 :(得分:1)

更新:factory_boy现在处理它了!

在最新版本的factory_boy(今天2.8.1)中,现在可以force the sequence counter进入定义值:

  

按每次通话强制执行该值

     

为了强制计数器进行特定的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

答案 3 :(得分:0)

第三种也是最简单的方法:

# 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

我自己只是从Factory Boy开始,也没有太多的Python经验,所以我可能会遗漏一些东西,但你会看到我要去的地方。为了更清楚,我想我实际上更喜欢它是关键的:

class BookFactory(factory.Factory, title_seq_start=-1):
...
book = factories.BookFactory(title_seq_start=512).create()