【问题标题】:Python factory_boy library m2m in Django model?Django模型中的Python factory_boy库m2m?
【发布时间】:2012-04-23 15:28:33
【问题描述】:

我目前正在使用factory_boy 在我的测试中创建夹具。 Factory_boy 文档只提到了 SubFactory,它的作用类似于模型中的 ForeignKey 字段。但是,ManyToMany 关联上没有任何内容。如果我有一个以下 Post 模型,我将如何为它创建一个工厂?

class Post(models.Model):
    title = models.CharField(max_length=100)
    tags = models.ManyToManyField('tags.Tag')

class PostFactory(factory.Factory):
    FACTORY_FOR = Post

    title = 'My title'
    tags = ???

【问题讨论】:

  • 嘿@Ngo 你得到一个有效的答案了吗?
  • @Daryl:覆盖 _prepare 似乎是最简单的解决方案 :)

标签: python django testing factory fixtures


【解决方案1】:

post_generation hook 怎么样 - 我假设您使用的是较新版本的 factory_boy

import random
import factory

class PostFactory(factory.Factory):
    FACTORY_FOR = Post
    title = factory.Sequence(lambda n: "This is test title number" + n)
    @factory.post_generation(extract_prefix='tags')
    def add_tags(self, create, extracted, **kwargs):
        # allow something like PostFactory(tags = Tag.objects.filter())
        if extracted and type(extracted) == type(Tag.objects.all()):
            self.tags = extracted
            self.save()
        else:
            if Tag.objects.all().count() < 5:
                TagFactory.create_batch(5, **kwargs)
            for tag in Tag.objects.all().order_by('?')[:random.randint(1, 5)]:
                self.tags.add(tag)

请注意,您可以使用PostFactory(tags__field = 'some fancy default text'),但我建议使用序列创建良好的TagFactory ...

你应该可以绑定PostFactory(tags = Tag.objects.filter()) 但是这部分没有测试...

【讨论】:

    【解决方案2】:

    您可以覆盖_prepare 类方法:

    class PostFactory(Factory):
        FACTORY_FOR = Post
    
        title = 'My title'
    
        @classmethod
        def _prepare(cls, create, **kwargs):
            post = super(PostFactory, cls)._prepare(create, **kwargs)
            if post.id:
                post.tags = Tag.objects.all()
            return post
    

    请注意,如果帖子没有 ID,则无法为帖子添加标签。

    【讨论】:

      【解决方案3】:

      我没有测试,但是有什么问题:

      class PostFactory(factory.Factory):
          FACTORY_FOR = Post
          title = 'My title'
      
      class TagFactory(factory.Factory):
          FACTORY_FOR = Tag
      
      post = PostFactory()
      tag = TagFactory()
      post.tags.add(tag)
      

      【讨论】:

      • 是的,这行得通。但我想这样做: post = PostFactory() 假设自动添加 4 个标签,而无需手动指定 post.tags.add(tag)
      • 我认为 factory_boy 不允许这样做。但是你为什么不创建一个为你做这件事的函数呢? def PostFactoryWithFourTags(): post = PostFactory() for _ in xrange(4): post.tags.add(TagFactory() return post
      猜你喜欢
      • 2012-12-24
      • 1970-01-01
      • 2020-03-30
      • 2022-01-22
      • 1970-01-01
      • 2010-10-22
      • 1970-01-01
      • 2011-03-07
      • 1970-01-01
      相关资源
      最近更新 更多