Я продолжаю сталкиваться с проблемами с моими фабриками, когда две или более модели имеют общий внешний ключ, и каждая из них создает свой собственный объект, когда у них должен быть один и тот же.
Чтобы проиллюстрировать проблему, вот упрощенная структура модели:
class Language (models.Model):
code = models.CharField(max_length=3, unique=True)
class Audio(models.Model):
language = models.ForeignKey(Language)
soundfile = models.FileField()
class Subtitles(models.Model):
language = models.ForeignKey(Language)
text = models.TextField()
class Recording(models.Model):
audio = models.ForeignKey(Audio)
subtitles = models.ForeignKey(Subtitles)
Таким образом, у Recording
есть Audio
и Subtitles
, и у обоих есть Language
, который уникален для каждого языкового кода.
Вот заводы для этой структуры.
class LanguageFactory(factory.django.DjangoModelFactory):
class Meta:
model = Language
class AudioFactory(factory.django.DjangoModelFactory):
class Meta:
model = Audio
language = factory.SubFactory(LanguageFactory, code='en1')
class SubtitlesFactory(factory.django.DjangoModelFactory):
class Meta:
model = Subtitles
language = factory.SubFactory(LanguageFactory, code='en1')
class RecordingFactory(factory.django.DjangoModelFactory):
class Meta:
model = Recording
audio = factory.SubFactory(AudioFactory)
subtitles = factory.SubFactory(SubtitlesFactory)
Это очень распространенный случай, когда звук и субтитры имеют один и тот же язык, поскольку обычно это просто стенограмма. Поэтому я хочу, чтобы RecordingFactory по умолчанию имела аудио и субтитры с языком «en1» в качестве кода, как это отражено в приведенных выше фабриках.
Но поскольку каждая фабрика пытается создать свой собственный экземпляр языка, создание экземпляра RecordingFactory с помощью recording = RecordingFactory()
(что я часто делаю) вызывает исключение:
IntegrityError: UNIQUE constraint failed: recordings_language.code
Чтобы решить эту проблему, я могу сделать что-то вроде этого:
language = LanguageFactory(code='en1')
recording = RecordingFactory(subtitles__language=language, audio__language=language)
Но это многословно. В моем реальном проекте у меня еще больше связей, поэтому иногда мне нужно указать язык в трех или четырех местах, иногда на четырех уровнях в глубину. Вместо этого я хотел бы иметь возможность указать значение по умолчанию, которое либо создается, либо используется, если оно уже существует.
Каков правильный способ обойти это, если он существует?