Factory Boy 及相关对象创建
Factory Boy and related objects creation
假设您以这种方式关联了这些 Django 模型:
class Service:
restaurant = models.ForeignKey(Restaurant)
hist_day_period = models.ForeignKey(DayPeriod)
class DayPeriod:
restaurant = models.ForeignKey(Restaurant)
我想创建一个 Service
对象,使用工厂。它应该创建所有 3 个模型,但使用 相同的 餐厅。
使用此代码:
class ServiceFactory(factory.django.DjangoModelFactory):
class Meta:
model = Service
restaurant = factory.SubFactory('restaurants.factories.RestaurantFactory')
hist_day_period = factory.SubFactory(
'day_periods.factories.DayPeriodFactory', restaurant=restaurant)
工厂男孩将创建 2 家不同的餐厅:
s1 = ServiceFactory.create()
s1.restaurant == s1.hist_day_period.restaurant
>>> False
知道怎么做吗?我不清楚是否应该使用 related factors
而不是 SubFactory
来完成此操作。
我反复讨论过从工厂内部或单独创建相关对象或 FK 对象是否有意义。正如您已经发现的那样,您不一定 想要 每次致电 ServiceFactory()
时都能找到一家新餐厅。我认为您最好让它们保持简单,但代价是不得不使用稍微冗长的调用代码。
注释掉 restaurant = factory.SubFactory
行,然后像这样给您的工厂打电话:
restaurant = Restaurant.objects.get(foo='bar')
ServiceFactory.create_batch(3, restaurant=restaurant)
或者,如果您确实想使用工厂来创建餐厅,但您只想创建一个餐厅:
restaurant = RestaurantFactory()
ServiceFactory.create_batch(3, restaurant=restaurant)
IOTW,让你的工厂做出尽可能少的假设,这样你就可以灵活地构建你需要的任何数据结构,这些数据结构来自测试或系统的不同部分。
您想使用 factoryboy 的 parents 和 SelfAttribute
class ServiceFactory(factory.django.DjangoModelFactory):
class Meta:
model = Service
restaurant = factory.SubFactory('restaurants.factories.RestaurantFactory')
hist_day_period = factory.SubFactory(
'day_periods.factories.DayPeriodFactory',
restaurant=factory.SelfAttribute('..restaurant')
)
通过这个测试应用,我得到了
In [1]: from service.tests import ServiceFactory
In [2]: s1 = ServiceFactory.create()
In [3]: s1.restaurant == s1.hist_day_period.restaurant
Out[3]: True
In [4]: s1.restaurant_id
Out[4]: 4
In [5]: s1.hist_day_period.restaurant_id
Out[5]: 4
您可以使用带有查询集的 Iterator
而不是 SubFactory
。
例如:
class ServiceFactory(factory.django.DjangoModelFactory):
class Meta:
model = Service
restaurant = factory.Iterator(models.Restaurant.object.all())
hist_day_period = factory.SubFactory(
'day_periods.factories.DayPeriodFactory', restaurant=restaurant)
不过,我不确定创建 Restaurant
的最佳位置。在我们的代码库中,我重写了 DiscoverRunner
并在那里创建了用于此目的的模型(在 setup_databases
中,这感觉就像是 hack)。
假设您以这种方式关联了这些 Django 模型:
class Service:
restaurant = models.ForeignKey(Restaurant)
hist_day_period = models.ForeignKey(DayPeriod)
class DayPeriod:
restaurant = models.ForeignKey(Restaurant)
我想创建一个 Service
对象,使用工厂。它应该创建所有 3 个模型,但使用 相同的 餐厅。
使用此代码:
class ServiceFactory(factory.django.DjangoModelFactory):
class Meta:
model = Service
restaurant = factory.SubFactory('restaurants.factories.RestaurantFactory')
hist_day_period = factory.SubFactory(
'day_periods.factories.DayPeriodFactory', restaurant=restaurant)
工厂男孩将创建 2 家不同的餐厅:
s1 = ServiceFactory.create()
s1.restaurant == s1.hist_day_period.restaurant
>>> False
知道怎么做吗?我不清楚是否应该使用 related factors
而不是 SubFactory
来完成此操作。
我反复讨论过从工厂内部或单独创建相关对象或 FK 对象是否有意义。正如您已经发现的那样,您不一定 想要 每次致电 ServiceFactory()
时都能找到一家新餐厅。我认为您最好让它们保持简单,但代价是不得不使用稍微冗长的调用代码。
注释掉 restaurant = factory.SubFactory
行,然后像这样给您的工厂打电话:
restaurant = Restaurant.objects.get(foo='bar')
ServiceFactory.create_batch(3, restaurant=restaurant)
或者,如果您确实想使用工厂来创建餐厅,但您只想创建一个餐厅:
restaurant = RestaurantFactory()
ServiceFactory.create_batch(3, restaurant=restaurant)
IOTW,让你的工厂做出尽可能少的假设,这样你就可以灵活地构建你需要的任何数据结构,这些数据结构来自测试或系统的不同部分。
您想使用 factoryboy 的 parents 和 SelfAttribute
class ServiceFactory(factory.django.DjangoModelFactory):
class Meta:
model = Service
restaurant = factory.SubFactory('restaurants.factories.RestaurantFactory')
hist_day_period = factory.SubFactory(
'day_periods.factories.DayPeriodFactory',
restaurant=factory.SelfAttribute('..restaurant')
)
通过这个测试应用,我得到了
In [1]: from service.tests import ServiceFactory
In [2]: s1 = ServiceFactory.create()
In [3]: s1.restaurant == s1.hist_day_period.restaurant
Out[3]: True
In [4]: s1.restaurant_id
Out[4]: 4
In [5]: s1.hist_day_period.restaurant_id
Out[5]: 4
您可以使用带有查询集的 Iterator
而不是 SubFactory
。
例如:
class ServiceFactory(factory.django.DjangoModelFactory):
class Meta:
model = Service
restaurant = factory.Iterator(models.Restaurant.object.all())
hist_day_period = factory.SubFactory(
'day_periods.factories.DayPeriodFactory', restaurant=restaurant)
不过,我不确定创建 Restaurant
的最佳位置。在我们的代码库中,我重写了 DiscoverRunner
并在那里创建了用于此目的的模型(在 setup_databases
中,这感觉就像是 hack)。