{"id":1063,"library":"factory-boy","title":"factory-boy","description":"factory-boy is a versatile test fixtures replacement for Python, based on thoughtbot's factory_bot for Ruby. It helps generate fake data efficiently and declaratively for various ORMs like Django, SQLAlchemy, and MongoEngine, supporting multiple build strategies and factory inheritance.","status":"active","version":"3.3.3","language":"python","source_language":"en","source_url":"https://github.com/FactoryBoy/factory_boy","tags":["testing","fixtures","factory","data generation","ORM","Django","SQLAlchemy"],"install":[{"cmd":"pip install factory-boy","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Commonly integrated for generating realistic, random data for factory attributes.","package":"Faker","optional":true}],"imports":[{"note":"The primary `Factory` class is typically imported from the `factory` namespace.","wrong":"from factory_boy import Factory","symbol":"Factory","correct":"import factory\n\nclass MyFactory(factory.Factory): ..."},{"note":"Used for generating realistic, randomized data.","symbol":"Faker","correct":"import factory\n\nclass MyFactory(factory.Factory):\n    name = factory.Faker('name')"},{"note":"Generates sequential values, often used for unique IDs.","symbol":"Sequence","correct":"import factory\n\nclass MyFactory(factory.Factory):\n    id = factory.Sequence(lambda n: n)"},{"note":"Evaluates its argument when the object is built, often dependent on other attributes of the generated object.","symbol":"LazyAttribute","correct":"import factory\n\nclass MyFactory(factory.Factory):\n    full_name = factory.LazyAttribute(lambda o: f'{o.first_name} {o.last_name}')"},{"note":"Used to create and link related objects, calling another factory.","symbol":"SubFactory","correct":"import factory\n\nclass UserFactory(factory.Factory): ...\nclass ProfileFactory(factory.Factory):\n    user = factory.SubFactory(UserFactory)"},{"note":"Specific factory for Django ORM models, automatically handling `save()` behavior during `create()`.","symbol":"DjangoModelFactory","correct":"from factory.django import DjangoModelFactory\n\nclass UserFactory(DjangoModelFactory):\n    class Meta:\n        model = User"},{"note":"Specific factory for SQLAlchemy models, requiring a session object in `Meta.sqlalchemy_session`.","symbol":"SQLAlchemyModelFactory","correct":"from factory.alchemy import SQLAlchemyModelFactory\n\nclass UserFactory(SQLAlchemyModelFactory):\n    class Meta:\n        model = User\n        sqlalchemy_session = db_session"}],"quickstart":{"code":"import factory\n\nclass User:\n    def __init__(self, first_name, last_name, email, is_admin=False):\n        self.first_name = first_name\n        self.last_name = last_name\n        self.email = email\n        self.is_admin = is_admin\n\n    def __str__(self):\n        return f'{self.first_name} {self.last_name} ({self.email})'\n\nclass UserFactory(factory.Factory):\n    class Meta:\n        model = User\n\n    first_name = factory.Faker('first_name')\n    last_name = factory.Faker('last_name')\n    email = factory.LazyAttribute(lambda o: f'{o.first_name}.{o.last_name}@example.com'.lower())\n    is_admin = False\n\n# Create a basic user\nuser = UserFactory()\nprint(f\"Created user: {user}\")\n\n# Create an admin user\nadmin_user = UserFactory(is_admin=True)\nprint(f\"Created admin user: {admin_user}\")\n\n# Create a user with specific name\nspecific_user = UserFactory(first_name='John', last_name='Doe')\nprint(f\"Created specific user: {specific_user}\")","lang":"python","description":"Define a simple Python class and then create a `factory.Factory` subclass for it. Use `factory.Faker` for realistic data and `factory.LazyAttribute` for interdependent fields. Instances can be created by calling the factory, with keyword arguments overriding default attributes."},"warnings":[{"fix":"Upgrade to Python 3.8+ and supported Django versions. Review the official changelog for specific removals and re-implementations.","message":"Major breaking changes occurred in the transition from factory-boy 2.x to 3.x, including dropping support for Python 2, Python 3.4, Django 2.0, and Django 2.1.","severity":"breaking","affected_versions":"2.x to 3.x"},{"fix":"Migrate your ORM-backed factories to inherit from `factory.django.DjangoModelFactory` or `factory.alchemy.SQLAlchemyModelFactory`.","message":"For plain `factory.Factory` subclasses, `create()` no longer calls `objects.create()` for ORM models. For Django or SQLAlchemy models, you must now use `DjangoModelFactory` or `SQLAlchemyModelFactory` respectively to ensure persistence to the database when calling `create()`.","severity":"breaking","affected_versions":"2.x to 3.x"},{"fix":"Refactor factory definitions to use the `Meta` class pattern (e.g., `class Meta: model = MyModel`).","message":"Old class-level attributes like `FACTORY_FOR`, `ABSTRACT_FACTORY`, `FACTORY_STRATEGY` are deprecated. They should now be defined within a nested `Meta` class using `model`, `abstract`, and `strategy` respectively.","severity":"deprecated","affected_versions":"2.x to 3.x"},{"fix":"If your `post_generation` hooks modify the instance, set `skip_postgeneration_save = True` in `Meta` and explicitly call `instance.save()` within your post-generation hook, typically guarding it with `if create:`.","message":"The default behavior of `_after_postgeneration` for `DjangoModelFactory` changed. It will no longer automatically save the instance after post-generation hooks in future releases. This often results in `DeprecationWarning` if not handled.","severity":"deprecated","affected_versions":"3.x"},{"fix":"Use `factory.List()`, `factory.Dict()`, or `factory.LazyAttribute` to ensure each instance receives a unique mutable object. Example: `my_list = factory.List([1, 2, 3])` or `my_dict = factory.LazyAttribute(lambda o: {})`.","message":"Defining mutable fields (e.g., lists, dictionaries) directly at the factory class level can lead to all generated instances sharing the same mutable object. Changes in one instance will propagate to others.","severity":"gotcha","affected_versions":"All"},{"fix":"Always specify attribute overrides using keyword arguments in your factory call (e.g., `MyFactory(name='Custom Name')`).","message":"Overriding attributes directly at the class level (e.g., `MyFactory.name = 'Fixed'`) is an anti-pattern and can lead to unpredictable behavior, especially in parallel test runs, as it modifies the default for all future objects.","severity":"gotcha","affected_versions":"All"}],"env_vars":null,"last_verified":"2026-05-12T23:24:27.822Z","next_check":"2026-06-30T00:00:00.000Z","problems":[{"fix":"For `factory-boy` versions 3.0 and above, ensure you are importing `DjangoModelFactory` from `factory.django`. If using an older version (pre-3.0), import it directly from `factory`. Also, confirm that `factory-boy` is installed (`pip install factory-boy`) and your virtual environment is activated.","cause":"This error typically occurs when attempting to import `DjangoModelFactory` from the `factory.django` module in older `factory-boy` versions (prior to 3.0) or when `factory-boy` is not installed or the virtual environment is not active. Before version 3.0, `DjangoModelFactory` was directly available under the `factory` namespace.","error":"ModuleNotFoundError: No module named 'factory.django'"},{"fix":"Inside your factory class, define a `Meta` inner class and set its `model` attribute to the actual Python class of the model you intend to create instances of (e.g., `model = myapp.models.MyModel`), not a string or an instance.","cause":"This error occurs when a `factory.Factory` subclass, especially `DjangoModelFactory`, does not have its `Meta.model` attribute correctly defined, meaning the factory doesn't know which model it should generate instances for.","error":"FactoryError: No model set on <FactoryName>Factory"},{"fix":"Ensure you are inheriting from `factory.django.DjangoModelFactory` for Django models. If the error persists, pass the actual model class to `Meta.model` (e.g., `model = myapp.models.MyModel`) instead of a string path.","cause":"This `AttributeError` often arises in Django contexts when a `DjangoModelFactory`'s `Meta.model` is incorrectly set to a string literal (e.g., `'myapp.MyModel'`) and an older `factory-boy` version or an improper interaction attempts to access model attributes like `pk` or `objects` directly on this string. While `DjangoModelFactory` *does* support string references for `model`, this specific error points to a situation where the string is not correctly resolved to a model class during an operation that expects an actual model object, or when `factory.Factory` is used instead of `factory.django.DjangoModelFactory`.","error":"AttributeError: 'str' object has no attribute 'pk'"},{"fix":"For any model fields that require unique values, use `factory.Sequence(lambda n: f'unique_value_{n}')` to generate distinct values for each instance. If you intend to retrieve existing objects instead of creating duplicates, properly configure `Meta.django_get_or_create = ('unique_field_name',)` with the fields that uniquely identify an object.","cause":"This database error typically occurs in Django tests when `factory-boy` creates model instances with values that violate unique constraints defined in your database schema, often due to not using `factory.Sequence` for unique fields or misconfiguring `django_get_or_create`.","error":"django.db.utils.IntegrityError: duplicate key value violates unique constraint"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"3.3.3","cli_name":"","cli_version":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","installed_version":"3.3.3","pypi_latest":"3.3.3","is_stale":false,"results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.32,"mem_mb":10.2,"disk_size":"42.5M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.41,"mem_mb":10.2,"disk_size":"42.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.7,"import_time_s":0.23,"mem_mb":10.2,"disk_size":"43M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.23,"mem_mb":10.2,"disk_size":"43M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.39,"mem_mb":10.8,"disk_size":"43.7M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.53,"mem_mb":10.8,"disk_size":"43.6M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.9,"import_time_s":0.37,"mem_mb":10.8,"disk_size":"44M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.35,"mem_mb":10.8,"disk_size":"44M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.34,"mem_mb":10.4,"disk_size":"35.5M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.43,"mem_mb":10.4,"disk_size":"35.3M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.8,"import_time_s":0.38,"mem_mb":10.4,"disk_size":"36M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.37,"mem_mb":10.4,"disk_size":"36M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.32,"mem_mb":10.5,"disk_size":"35.2M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.55,"mem_mb":10.5,"disk_size":"34.9M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":2.7,"import_time_s":0.34,"mem_mb":10.5,"disk_size":"36M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.35,"mem_mb":10.5,"disk_size":"35M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":null,"import_time_s":0.28,"mem_mb":10,"disk_size":"43.1M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.36,"mem_mb":10,"disk_size":"43.1M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":"wheel","failure_reason":null,"import_side_effects":"clean","install_time_s":3.5,"import_time_s":0.28,"mem_mb":10,"disk_size":"44M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"factory-boy","exit_code":0,"wheel_type":null,"failure_reason":null,"import_side_effects":null,"install_time_s":null,"import_time_s":0.29,"mem_mb":10,"disk_size":"44M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}