Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random model values inside list subfactory elements

I cannot find an answer to my question. The thing is that I want to generate an User factory model where inside will be a subfactory List with Addresses. Each Addresses element must have different/random values (I mean that each element has non-repeatable unique values).

In my current implementation, all of the elements have the same values (maybe seeding is necessary?)

Actual code:

from pydantic import BaseModel
from factory import Factory, List, Subfactory


class Address(BaseModel):
    Name: str


class User(BaseModel):
    Addresses: list[Address]


class AddressFactory(Factory):
    Name = fake.name()

    class Meta:
        model = Address


class UserFactory(Factory):
    Addresses = List([SubFactory(AddressFactory) for _ in range(3)])

    class Meta:
        model = User

Actual output:

> UserFactory()
> User(Addresses=[Address(Name='Isa Merkx'), Address(Name='Isa Merkx'), Address(Name='Isa Merkx')])

Desired Output:

> UserFactory()
> User(Addresses=[Address(Name='Isa Merkx'), Address(Name='John Smith'), Address(Name='Elon Musk')])
like image 727
Radosław Hryniewicki Avatar asked Sep 13 '26 12:09

Radosław Hryniewicki


1 Answers

You should use the LazyAttribute to get a different value each time.

from typing import List
from pydantic import BaseModel
import factory
from faker import Faker

fake = Faker('en_GB') # <-- missing from the original example


class Address(BaseModel):
    Street: str
    HouseNumber: str
    City: str
    Postcode: str


class AddressFactory(factory.Factory):
    Street = factory.LazyAttribute(lambda _: fake.street_name()) # <-- Lazy load the attribute values
    HouseNumber = factory.LazyAttribute(lambda _: fake.building_number())
    City = factory.LazyAttribute(lambda _: fake.city())
    Postcode = factory.LazyAttribute(lambda _: fake.postcode())

    class Meta:
        model = Address


class User(BaseModel):
    Addresses: List[Address]


class UserFactory(factory.Factory):
    Addresses = factory.List([factory.SubFactory(AddressFactory) for _ in range(3)])

    class Meta:
        model = User


user = UserFactory()
user

The output:

User(Addresses=[Address(Street='Jade rapids', HouseNumber='3', City='Vanessaville', Postcode='B6H 2XA'), Address(Street='Wendy grove', HouseNumber='76', City='West Patricia', Postcode='WR5 0GL'), Address(Street='Smith ramp', HouseNumber='3', City='New Leslie', Postcode='L6 6JF')])
like image 89
thoroc Avatar answered Sep 15 '26 03:09

thoroc