You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Factory Boy让User、Profile、UserPhoto共享同一用户生成测试数据

问题:批量生成用户时自动创建关联的UserPhoto

我用假数据填充数据库,拥有User、Profile、UserPhoto三个独立模型,其中UserPhoto通过ForeignKey关联User。当前调用ProfileFactory.create_batch(10)可生成10个用户及对应的Profile,但我希望同时为每个用户生成2张UserPhoto(总计20张),且所有模型都关联同一用户数据。现有UserPhotoFactory的user字段配置存在疑问,请问如何调整代码实现该需求?

现有Factory代码

class UserFactory(DjangoModelFactory):

    class Meta:
        model = User

    email = factory.Faker('email')
    first_name = factory.Faker('first_name')
    birthday = factory.Faker('date_object')
    age = factory.Faker('pyint', min_value=18, max_value=100)
    is_staff = False
    is_active = True

class UserPhotoFactory(DjangoModelFactory):

    class Meta:
        model = UserPhoto

    user = factory.RelatedFactory(UserFactory) # 此处配置有问题
    order = factory.Faker('pyint', min_value=0, max_value=4)
    url = factory.Faker(
        'random_element', elements=[x for x in ['https://picsum.photos/seed/picsum/200/300', 'https://picsum.photos/seed/pssss/200/300', 'https://picsum.photos/seed/picwum/200/300']]
    )

class ProfileFactory(DjangoModelFactory):

    class Meta:
        model = Profile
    
    user = factory.SubFactory(UserFactory)
    bio = factory.LazyAttribute(lambda o: FAKE.paragraph(nb_sentences=5, ext_word_list=['abc', 'def', 'ghi', 'jkl']))

UserPhoto模型定义

class UserPhoto(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    order = models.PositiveIntegerField(null=True)
    url = models.CharField(max_length=220)

解决方案

1. 修正UserPhotoFactory的user字段配置

原代码中factory.RelatedFactory(UserFactory)用法错误,RelatedFactory是从父模型生成子模型,而非反向关联。这里应将UserPhoto的user字段设为factory.SubFactory(UserFactory),作为默认值方便单独创建照片,批量生成时会自动被关联的User覆盖。

2. 在UserFactory中添加批量生成UserPhoto的逻辑

使用factory.RelatedFactoryList让每个User创建时自动生成指定数量的UserPhoto,确保关联关系正确。

修改后的完整Factory代码

class UserFactory(DjangoModelFactory):
    class Meta:
        model = User

    email = factory.Faker('email')
    first_name = factory.Faker('first_name')
    birthday = factory.Faker('date_object')
    age = factory.Faker('pyint', min_value=18, max_value=100)
    is_staff = False
    is_active = True

    # 每个用户自动生成2张关联照片
    photos = factory.RelatedFactoryList(
        'your_app.factories.UserPhotoFactory',  # 替换为实际的UserPhotoFactory路径
        size=2,
        factory_related_name='user'
    )

class UserPhotoFactory(DjangoModelFactory):
    class Meta:
        model = UserPhoto

    user = factory.SubFactory(UserFactory)
    order = factory.Faker('pyint', min_value=0, max_value=4)
    url = factory.Faker(
        'random_element', elements=['https://picsum.photos/seed/picsum/200/300', 'https://picsum.photos/seed/pssss/200/300', 'https://picsum.photos/seed/picwum/200/300']
    )

class ProfileFactory(DjangoModelFactory):
    class Meta:
        model = Profile
    
    user = factory.SubFactory(UserFactory)
    bio = factory.LazyAttribute(lambda o: FAKE.paragraph(nb_sentences=5, ext_word_list=['abc', 'def', 'ghi', 'jkl']))

说明

  • RelatedFactoryList的size=2指定每个User生成2张UserPhoto
  • factory_related_name='user'对应UserPhoto模型中关联User的字段名
  • 调用ProfileFactory.create_batch(10)时,会自动创建10个User,每个User对应1个Profile和2个UserPhoto,所有对象关联关系完全匹配

内容的提问来源于stack exchange,提问作者rafaelHTML

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:12:02