Django App依赖循环

Rob*_*ing 24 python django dependencies

我正在开发一个Django应用程序,它有相当复杂的模型(它模拟大学 - 课程,模块,讲座,学生等)

我已将项目分为应用程序,以使整个事情更有条理(应用程序是课程,学校,人员,模块和时间段).我有一个问题,即一个应用程序中的模型可能依赖于另一个应用程序中的模型 - 所以我必须导入它.然后第二个应用程序依赖于第一个应用程序中的模型,因此有一个循环并且Python会引发错误.

人们如何处理这个问题?我知道应用程序应该相对"独立",但在这样的系统中,例如,使用ContentTypes将学生链接到模块是没有意义的.

有没有人有类似的项目可以评论这个案例?

Dan*_*man 56

如果您的依赖项是使用引用其他应用程序中的模型的外键,无需导入其他模型.您可以在ForeignKey定义中使用字符串:

class MyModel(models.Model):
    myfield = models.ForeignKey('myotherapp.MyOtherModel')
Run Code Online (Sandbox Code Playgroud)

这样就不需要导入MyOtherModel,所以没有循环引用.Django在内部解析字符串,它都按预期工作.


Jon*_*ley 5

下面的内容是我很久以前写的。现在读它,这对于OP的问题来说不是一个好的建议。他们可能应该将模型放入单个 Django 应用程序中。但以下是代码中依赖关系的一些一般背景,并且在中途提到了“将它们放入一组”解决方案:

忽略您的问题的 Django 方面,打破循环依赖关系的一般技术是将交叉引用项之一分解为新模块。例如,循环:

moduleA: class1, class2
                       |        ^
                       v        |
moduleB: class3, class4
Run Code Online (Sandbox Code Playgroud)

可能会变成:

moduleB2:              class4
                                    |
                                    v
moduleA: class1, class2
                        |
                        v
moduleB1: class3
Run Code Online (Sandbox Code Playgroud)

或者,您可以从 moduleA 中拆分类:

moduleA1: class1
                       | 
                       v
moduleB: class3, class4
                                    |
                                    v
moduleA2:               class2
Run Code Online (Sandbox Code Playgroud)

或两者:

moduleA1: class1
                       | 
                       v
moduleB1: class3

moduleB2:              class4
                                      |
                                      v
moduleA2               class2
Run Code Online (Sandbox Code Playgroud)

当然,如果 A 类和 B 类相互依赖,这没有任何帮助:

moduleA: class1
                    |    ^
                    v    |
moduleB: class2
Run Code Online (Sandbox Code Playgroud)

在这种情况下,也许它们应该位于同一个模块中(我怀疑这是 OP 应该使用的解决方案。将各种相互关联的模型类放入单个 Django 应用程序中):

moduleA: class1 <--->  class2
Run Code Online (Sandbox Code Playgroud)

或者也许可以以某种方式对类进行细分。例如,第一步可能是将 class2 需要的 class1 部分分解为新的 class3,两个原始类都依赖于该新的 class3:

moduleA: class1
                    |    |
                    |    v
moduleB:   |    class2
                    |     |
                    v    v
moduleC: class3(new!)
Run Code Online (Sandbox Code Playgroud)

这已经打破了循环。我们可能想更进一步,分解出第 1 类所依赖的第 2 类的部分:

moduleA:       class1
                         |     |
                         |     |
moduleB:        |     |     class2
                         |     |      |    |
                         |     v     v   |
moduleC:       |    class3   |
                        |                   |
                        v                 v
moduleD:       class4(new!)
Run Code Online (Sandbox Code Playgroud)

有时这种崩溃是很困难的。掌握它的窍门当然是一项需要付出努力才能学习的技能。如果进展不顺利,生成的片段看起来非常特别,针对您的问题,并且您会感觉通过将算法分解为多个片段,使算法变得更难以理解。但是,当这个过程顺利进行时,所得的片段感觉就像有用的新原语,人们可以想象它们可以在其他地方使用(即使这实际上并没有在您当前的项目中发生),并且使用它们可以使您的核心算法更容易理解。

(请记住,在一般情况下,上面的“依赖关系”箭头可以表示类之间的任何类型的依赖关系,可能是继承或组合等。一个类方法可能只是调用另一个类上的静态方法。当我们谈到“类”,所有这些都同样适用于其他逻辑块,例如相互依赖(即调用)的函数,或相互引用的数据库表。