Библиотека python factory_boy m2m в модели Django?

В настоящее время я использую factory_boy для создания светильников в своих тестах. factory_boy docs упоминается только о SubFactory, который может действовать как поле ForeignKey в модели. Однако в ассоциации ManyToMany не было ничего. Если бы у меня была следующая модель Post, как я мог бы создать для нее factory?

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 = ???

Ответ 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:

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

Обратите внимание, что вы не можете добавлять теги к сообщению, если сообщение не имеет идентификатора.

Ответ 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)