我该如何处理Google App Engine中的循环导入?

时间:2009-12-15 22:29:35

标签: python google-app-engine

如果我有“a.py”

from google.appengine.ext import db
class A(db.Model):
    db.ReferenceProperty(b.B)
    ...other stuff

和另一个文件“b.py”

from google.appengine.ext import db
class B(db.Model):
    db.ReferenceProperty(a.A)
    ...other stuff

似乎Python根本不允许循环依赖。通常我猜你会改变代码,这样两个类实际上可以解决自己而不直接相互导入。也许通过第三中间人来巩固他们对彼此的引用?但我不能只使用普通的中间类,因为所有类最终都需要持久保存到数据库中?是否有任何正确的解决方案来构造上述代码,使其有效?

我有一种感觉,我会得到很多“难闻的代码”,“解耦”,“糟糕的设计”等评论。所以我想问一下,如果你这么说,请说明你用一个实际的例子做什么。有没有任何解决方案可以让参考,类和模块保持原样?

谢谢。

4 个答案:

答案 0 :(得分:7)

解决方法是在至少一个不限制特定类的模型中使用ReferenceProperty,然后强制仅在您自己的代码中引用该类。

例如,

class A(db.Model):
  b = db.ReferenceProperty()

class B(db.Model):
  a = db.ReferenceProperty(A)

您可以将任何模型实例分配给b变量;只是确保你只分配实际的Bs。

答案 1 :(得分:1)

如果在同一模块中定义两个模型会发生什么?例如a_b.py

答案 2 :(得分:1)

根据documentation

  

ReferenceProperty还有另一个方便   功能:反向引用。当一个模特   有另一个ReferenceProperty   模型,每个被引用的实体得到一个   属性,其值为Query   返回的所有实体   引用它的第一个模型。

所以你应该可以使用自动添加的反向引用。

答案 3 :(得分:0)

从技术上讲,您可以使用交集表替换循环依赖项。

就我而言,我有非规范化模型,PlayerMatch

匹配和玩家之间的关系是多对多的,(玩家玩过一次或多次比赛,匹配参考一个或多个玩家)。

我需要的是什么:

class Match(db.Model):
    p1 = db.ReferenceProperty( Player )
    p2 = db.ReferenceProperty( Player )

class Player(db.Model):
    # Remember what match player is currently in, for victor reporting
    currentMatch = db.ReferenceProperty( Match )

选项0:Wooble建议的内容

选项1:将其标准化(使用交集表)

class Match(db.Model):
    # ...

class Player(db.Model):
    # ...

# Every match has multiple entries here (as many 1 for
# each player-in-match entry).  This will make retrieval
# slower, but more-correct (it is "normalized" now)
class PlayersInMatches(db.Model):
    player=db.ReferenceProperty(Player)
    match=db.ReferenceProperty(Match)
    isCurrent=db.BooleanProperty()