2016-09-06 48 views
3

当两个或多个模型具有共同的外键时,我一直遇到与工厂有关的问题,并且每个模型都应该有相同的外键时创建它们自己的对象。如何使用相同的外键为Django模型创建工厂男孩工厂

为了说明问题,这里是一个简化的模型结构:

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具有AudioSubtitles,并且两个那些有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) 

但是这是冗长的。在我的真实项目中,我有更多的联系,所以有时我需要在三到四个地方指定语言,有时甚至四个级别。相反,我希望能够指定一个默认值,如果它已经存在,可以创建或使用它。

如果存在这个问题,正确的方法是什么?

回答

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')) 
+0

谢谢,我不知道我可以使用PARAMS这样。将尝试出来 –

+3

我不能得到这个工作,得到以下错误'CyclicDefinitionError:语言的循环懒惰属性定义;周期在['语言']中找到。' –

+1

我正面临类似的问题。你找到了解决方案吗? – silentser