Указать имена столбцов Factory db с помощью FactoryBoy в Django Test?

У меня есть несколько неуправляемых моделей, для которых я пытаюсь разработать некоторые фабрики, чтобы я мог собрать несколько тестов. Проблема в том, что у пары из них есть имена db_column, и это приводит к ошибке в фабрике.

Мои модели выглядят следующим образом:


class Identity(models.Model):
    id = models.IntegerField(db_column="identityID", primary_key=True)
    person_id = models.IntegerField(db_column="personID")
    birth_date = models.DateField(db_column="birthdate")
    gender = models.CharField(db_column="gender", max_length=1)

    class Meta(object):
        # This is 'True' when testing so it's treated like a normal model
        managed = getattr(settings, "UNDER_TEST", False)
        db_table = "identity"

class Person(models.Model):
    id = models.IntegerField(db_column="personID", primary_key=True)
    identity = models.ForeignKey(
        Identity, db_column="currentIdentityID", on_delete=models.PROTECT
    )
    ticket_number = models.IntegerField(db_column="ticketNumber")

    class Meta(object):
        # This is 'True' when testing so it's treated like a normal model
        managed = getattr(settings, "UNDER_TEST", False)
        db_table = "person"

class YearTerm(models.Model):
    active = models.BooleanField(default=False)
    name = models.CharField(max_length=50)
    created_by = models.ForeignKey(
        Person, on_delete=models.PROTECT
    )

    class Meta:
        # This is 'True' when testing so it's treated like a normal model
        managed = getattr(settings, "UNDER_TEST", False)
        db_table = "[ALTS].[yearterm]"

Мои фабрики выглядят следующим образом:

class IdentityFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Identity

    @classmethod
    def _setup_next_sequence(cls):
        try:
            return Identity.objects.latest("id").id + 1
        except Identity.DoesNotExist:
            return 1

    id = factory.Sequence(lambda n: n)
    person_id = factory.Sequence(lambda n: n)
    birth_date = factory.fuzzy.FuzzyDateTime(timezone.now())
    gender = factory.Faker("random_element", elements=[x[0] for x in GENDERS])


class PersonFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Person

    @classmethod
    def _setup_next_sequence(cls):
        try:
            return Person.objects.latest("id").id + 1
        except Person.DoesNotExist:
            return 1

    id = factory.Sequence(lambda n: n)
    identity = factory.RelatedFactory(
        IdentityFactory,
        person_id=factory.SelfAttribute("..id"),
    )
    ticket_number = factory.Faker("random_int", min=1000, max=40000)

class YearTermFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = YearTerm
        django_get_or_create = ("name",)

    active = Iterator([True, False])
    name = FuzzyChoice(["Occasionally", "Sometimes", "Always"])
    created_by = SubFactory(PersonFactory)

Мой тестовый пример чрезвычайно прост:

class TestCaseYearTerm(TestCase):
    def test_create(self):
        """
        Test the creation of a YearTerm model using a factory
        """
        year_term = YearTermFactory.create()
        self.assertEqual(YearTerm.objects.count(), 1)

Но я получаю следующую ошибку: django.db.utils.IntegrityError: NOT NULL constraint failed: person.currentIdentityID

Мне кажется, что это происходит потому, что я указываю db_column имя в модели, но я не уверен, как исправить это в FactoryBoy или заставить factory boy добавлять определенное имя к атрибутам фабрик при их создании.

Любая помощь будет принята с благодарностью!

Модели могут быть улучшены. ОП имеет модели Person и Identity и хочет, чтобы одна Person соответствовала только одной Identity (как профиль пользователя/персоны). ОП может достичь этого с помощью OneToOneField. Таким образом, можно отредактировать модель Identity OP следующим образом

class Identity(models.Model):
    person = models.OneToOneField(Person, on_delete=models.CASCADE)

Обратите внимание, что я не использую person_id. Использование _id в полях модели Django для OneToOneField и Foreign является анти-паттерном. Также, в модели ОП Person удалите поле identity, поскольку оно больше не нужно. После этого ОП нужно будет выполнить makemigrations.

Тогда заводы ОП станут проще

import factory
from factory import SubFactory
from factory.django import DjangoModelFactory

class IdentityFactory(DjangoModelFactory):
    person = SubFactory(PersonFactory)
     
    class Meta:
        model = Identity

Не забудьте также удалить идентификацию из PersonFactory.

Вернуться на верх