How to create a uuid func for a lazy function

The important bit

class YourModelFactory(DjangoModelFactory):
    uuid = factory.LazyFunction(create_uuid4_str)

The problem?

In django you can use factory-boy to create instances of you models, which will automatically instantiate it with realistic data.

For the following model

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=300)
    uuid = models.UUIDField()

    def __str__(self):
        return f"{self.name} {self.uuid}"

then you could write a factory like so, and it would work. The problem is that if you made some in bulk it might not work as expected.

import uuid

from django.contrib.auth.models import Person

import factory
from factory.django import DjangoModelFactory


class PersonFactory(DjangoModelFactory):
    name = factory.Sequence(lambda n: f"Name{n:03d}")
    uuid = str(uuid.uuid4())

The solution

so calling PersonFactory.create_batch(size=3) would actually create Persons with unique names but same uuid.

Call it again and it would create Persons with 3 unique names but another uuid, but the same for all 3.

So what you need it to use the lazy function and pass in a function. We can do this very simply by passing in an anonymous function (a lambda). I'm so used to passing in args to a lambda, but you don't need to.

If I was writing the function fully it would be something like

def create_uuid4_str():
    return str(uuid.uuid4())

but as a lambda it is just

lambda: str(uuid.uuid4())

so using this firstly with the function and factory boy it is

class PersonFactory(DjangoModelFactory):
    name = factory.Sequence(lambda n: f"Name{n:03d}")
    uuid = factory.LazyFunction(create_uuid4_str)

def create_uuid4_str():
    return str(uuid.uuid4())

and with the lambda

class PersonFactory(DjangoModelFactory):
    name = factory.Sequence(lambda n: f"Name{n:03d}")
    uuid = factory.LazyFunction(lambda: str(uuid.uuid4()))

And now it works with bulk creation