pytest-factoryboy icon indicating copy to clipboard operation
pytest-factoryboy copied to clipboard

ManyToMany PostGeneration class

Open stevelacey opened this issue 7 years ago • 0 comments

Most m2m relation handling for factories in Django is pretty simple, is this of interest?

class ManyToManyPostGeneration(factory.PostGeneration):
    """
    Simplified factory post_generation for many-to-many relationships - sets values passed to the collection
    https://factoryboy.readthedocs.io/en/latest/recipes.html?highlight=many#simple-many-to-many-relationship

    Arguments:
        name: the name of the many-to-many relation

    Usage:
        You can pass the factory a list of model instances

        - article_factory.create(tags=LazyFixture(lambda tag: [tag])))

        Or you can use the parametrize decorator

        - @pytest.mark.parametrize('article__tags', [LazyFixture(lambda tag: [tag])])
    """
    def __init__(self, name):
        def func(self, create, extracted, **kwargs):
            if create and extracted:
                getattr(self, name).set(extracted)
        func.__name__ = name
        return super().__init__(func)

Makes basic m2m declarations as simple as

class ArticleFactory(factory.django.DjangoModelFactory):
    tags = ManyToManyPostGeneration('tags')

You can also define and use the inverse side too

class TagFactory(factory.django.DjangoModelFactory):
    articles = ManyToManyPostGeneration('articles')

I'd drop the string arg but I couldn't figure out how to know the relation name otherwise

Another thought was whether it should add or set – the examples provided use add but I figure given the whole list is passed in an explicit set is probably what is expected (i.e. clobber)

Any interest in something like this in pytest-factoryboy?

stevelacey avatar Feb 04 '18 03:02 stevelacey