当两个或多个模型有一个共同的外键时,我一直遇到我的工厂的问题,每个模型都应该创建自己的对象。
为了说明问题,这里有一个简化的模型结构:
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'作为代码,如上面的工厂所示。
但是由于每个工厂都试图创建自己的语言实例,因此使用recording = RecordingFactory()
实例化RecordingFactory(我做了很多)会引发异常:
IntegrityError: UNIQUE constraint failed: recordings_language.code
要解决这个问题,我可以这样做:
language = LanguageFactory(code='en1')
recording = RecordingFactory(subtitles__language=language, audio__language=language)
但那很冗长。在我的真实项目中,我有更多的联系,所以有时我需要在三到四个地方指定语言,有时四个级别。相反,我希望能够指定创建或使用的默认值(如果已存在)。
如果有的话,有什么正确的方法?
答案 0 :(得分:2)
您可以使用Params
选项(http://factoryboy.readthedocs.io/en/latest/reference.html#parameters):
class RecordingFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Recording
class Params:
language = factory.SubFactory(Language)
subtitles = factory.SubFactory(SubtitlesFactory,
language=factory.SelfAttribute('language'))
audio = factory.SubFactory(AudioFactory,
language=factory.SelfAttribute('language'))