最近项目使用django重构,由于使用了代理类继承models中的类,为了可以使用代理类中的方法,models中的类的外键又是指向代理类的,毫无疑问这样发生了循环引用。
方案一(临时解决方案---不推荐):在代理类以及models中建立外键所需要引用时,from...import...全部采用局部引用。
此方案要写很多很多重复的from...import...显然不够优雅
方案二( 我们最终选择的方案---推荐):models中的外键所引用的类用引号括起来,这样在第一次加载的时候就算此类没有被加载也没有关系,只要你真正调用之前加载了这个类就不会出错,然后将这个文件中的所有的加载其他类的from...import语句放到文件的最下面。这样就是先加载上面全部的类,然后再去加载代理类。代理类中的from...import...也不需要局部引用,写在文件头部就没问题了。
方案三(改动太大,放弃):将“代理类继承model”的模式改成“model继承外部类”,改变继承方向。我觉得用一个写满属性的类去继承一个写满方法的类在设计上就怪怪的,也没有进行验证是否可行,遂放弃。
方案四(实验未成功):网上有的解决方案是使用import代替from,实验没成功
总结:
1.如果有能力就在架构设计之初尽量避免循环引用问题。特别是使用了继承、工厂、代理类的话要考虑清楚
2.user = models.ForeignKey(User)是可以写成user = models.ForeignKey('User'),这样在加载时可以忽略引用顺序问题,但是编译器就没办法提醒你这个类到底有没有引用,不过是小问题。
3.model中只要外键用的是字符串,from...import...是可以放在文件末尾的,不过编译器会提醒你from语句应该放在文件头,小问题。
注:最近加班加成了沙雕,晚些时候测试一下方案三和方案四,并把示例代码贴上来。