为什么 Django 的工厂男孩在我没有要求的时候试图创建一个工厂?

Why is Django's factory-boy trying to create a factory when I'm not asking it to?

我正在尝试使用 Django 的 factory-bot 模块为我的模型创建工厂。我也在使用 pytest。我创建了这些工厂 ...

import factory
from maps.models import CoopType, Coop
from address.models import AddressField
from phonenumber_field.modelfields import PhoneNumberField
from address.models import State, Country, Locality


class CountryFactory(factory.DjangoModelFactory):
    """
        Define Country Factory
    """
    class Meta:
        model = Country

    name = "Narnia"
    code = "NN"


class StateFactory(factory.DjangoModelFactory):
    """
        Define State Factory
    """
    class Meta:
        model = State 

    name = "Narnia"
    code = "NN"
    country = CountryFactory() 


class LocalityFactory(factory.DjangoModelFactory):
    """
        Define Locality Factory
    """
    class Meta:
        model = Locality 

    name = "Narnia"
    postal_code = "60605"
    state = StateFactory()

class AddressFactory(factory.DjangoModelFactory):
    """
        Define Address Factory
    """
    class Meta:
        model = Address

    street_number = "123"
    route = "Rd"
    raw = "123 Fake Rd" 
    formatted = "123 Fake Rd." 
    latitude = 87.1234
    longitude = -100.12342
    locality = LocalityFactory()


class CoopTypeFactory(factory.DjangoModelFactory):
    """
        Define Coop Type Factory
    """
    class Meta:
        model = CoopType

到目前为止,我有一个非常简单的测试文件。它只有一个测试...

import pytest
from django.test import TestCase
from .factories import CoopTypeFactory, CoopFactory


class ModelTests(TestCase):
    @classmethod
    def setUpTestData(cls):
        print("setUpTestData: Run once to set up non-modified data for all class methods.")
        #management.call_command('loaddata', 'test_data.yaml', verbosity=0)
        pass

    def setUp(self):
        print("setUp: Run once for every test method to setup clean data.")
        #management.call_command('flush', verbosity=0, interactive=False)
        pass

    @pytest.mark.django_db
    def test_coop_type_create(self):
        """ Test customer model """    # create customer model instance
        coop_type = CoopTypeFactory(name="Test Coop Type Name")
        assert coop_type.name == "Test Coop Type Name"

但是当我 运行 我的测试时,它死于抱怨我什至没有创建的工厂的重复密钥。

davea$ python manage.py test --settings=maps.test_settings
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
E
======================================================================
ERROR: tests.test_models (unittest.loader._FailedTest)
----------------------------------------------------------------------
ImportError: Failed to import test module: tests.test_models
Traceback (most recent call last):
  File "/Users/davea/Documents/workspace/chicommons/maps/web
...

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 434, in _find_test_path
    module = self._get_module_from_name(name)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/unittest/loader.py", line 375, in _get_module_from_name
    __import__(name)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/tests/test_models.py", line 3, in <module>
    from .factories import CoopTypeFactory, CoopFactory
  File "/Users/davea/Documents/workspace/chicommons/maps/web/tests/factories.py", line 19, in <module>
    class StateFactory(factory.DjangoModelFactory):
  File "/Users/davea/Documents/workspace/chicommons/maps/web/tests/factories.py", line 28, in StateFactory
    country = CountryFactory()
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 46, in __call__
    return cls.create(**kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 564, in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 141, in _generate
    return super(DjangoModelFactory, cls)._generate(strategy, params)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 501, in _generate
    return step.build()
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/builder.py", line 279, in build
    kwargs=kwargs,
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/base.py", line 315, in instantiate
    return self.factory._create(model, *args, **kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/factory/django.py", line 185, in _create
    return manager.create(*args, **kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/query.py", line 417, in create
    obj.save(force_insert=True, using=self.db)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/base.py", line 729, in save
    force_update=force_update, update_fields=update_fields)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/base.py", line 759, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/base.py", line 842, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/base.py", line 880, in _do_insert
    using=using, raw=raw)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/query.py", line 1125, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1280, in execute_sql
    cursor.execute(sql, params)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/django/db/backends/mysql/base.py", line 71, in execute
    return self.cursor.execute(query, args)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/MySQLdb/cursors.py", line 209, in execute
    res = self._query(query)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/MySQLdb/cursors.py", line 315, in _query
    db.query(q)
  File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.7/site-packages/MySQLdb/connections.py", line 239, in query
    _mysql.connection.query(self, query)
django.db.utils.IntegrityError: (1062, "Duplicate entry 'Narnia' for key 'name'")


----------------------------------------------------------------------
Ran 1 test in 0.000s

我做错了什么?为什么 Django 试图为我没有为其创建工厂的东西创建工厂?

您应该使用 factory.SubFactory 来定义外键关系

class LocalityFactory(factory.DjangoModelFactory):
    ...
    state = factory.SubFactory(StateFactory)

调用您 类 中的工厂正在创建实例