如何使用factory_boy为Django含筛选多对多字段的模型编写工厂类?
嘿,我来帮你搞定这个factory_boy工厂类的编写问题!针对你带筛选条件的同模型多对多字段,咱们一步步来实现:
第一步:先搞定依赖模型的工厂
首先,你的Places模型依赖User、Place,还有Place关联的Site模型(从limit_choices_to={'site__token': 'site1'}能看出来),所以得先给这些模型写基础工厂:
import factory from django.contrib.auth import get_user_model from .models import Site, Place, Places # 拿到User模型(兼容自定义User) User = get_user_model() # Site模型的工厂 class SiteFactory(factory.django.DjangoModelFactory): class Meta: model = Site # 默认生成随机token,同时定义子类专门生成site1的实例 token = factory.Faker('word') class Site1Factory(SiteFactory): token = 'site1' # Place模型的工厂 class PlaceFactory(factory.django.DjangoModelFactory): class Meta: model = Place # 默认关联随机Site,同样定义子类生成属于site1的Place site = factory.SubFactory(SiteFactory) name = factory.Faker('company') # 示例字段,替换成你实际的字段 class Site1PlaceFactory(PlaceFactory): site = factory.SubFactory(SiteFactory.Site1Factory) # User模型的工厂 class UserFactory(factory.django.DjangoModelFactory): class Meta: model = User username = factory.Faker('user_name') email = factory.Faker('email')
第二步:编写Places模型的核心工厂
这里重点处理带筛选条件的多对多字段place1和place2,用factory.post_generation装饰器来处理多对多关联(因为多对多需要主实例创建后才能添加关联):
class PlacesFactory(factory.django.DjangoModelFactory): class Meta: model = Places # 关联User实例 user = factory.SubFactory(UserFactory) # 处理place1字段:只能关联site__token='site1'的Place @factory.post_generation def place1(self, create, extracted, **kwargs): # 如果是build模式(不写入数据库),直接返回 if not create: return # 如果你手动传入了place1的实例列表,就用你传入的 if extracted: for place in extracted: self.place1.add(place) else: # 默认自动创建2个符合条件的site1 Place实例并关联 site1_places = PlaceFactory.Site1PlaceFactory.create_batch(2) self.place1.add(*site1_places) # 同理处理place2字段(假设它的筛选条件是site__token='site2',你可以按需修改) @factory.post_generation def place2(self, create, extracted, **kwargs): if not create: return if extracted: for place in extracted: self.place2.add(place) else: # 先定义site2的Site工厂子类,再生成对应的Place class Site2Factory(SiteFactory): token = 'site2' class Site2PlaceFactory(PlaceFactory): site = factory.SubFactory(Site2Factory) site2_places = Site2PlaceFactory.create_batch(2) self.place2.add(*site2_places)
怎么用这个工厂?
- 默认创建:
PlacesFactory()会自动生成关联的User、2个site1的Place给place1、2个site2的Place给place2 - 手动指定关联:
my_site1_place = PlaceFactory.Site1PlaceFactory(),然后PlacesFactory(place1=[my_site1_place])
这样写的好处是,既遵守了模型里limit_choices_to的筛选规则,又保持了工厂的灵活性,你既可以让工厂自动生成符合条件的实例,也能手动传入指定的实例。
内容的提问来源于stack exchange,提问作者pietà
相关产品推荐
相关产品推荐

