解决循环导入问题

时间:2014-07-20 11:25:51

标签: python mongodb flask mongoengine

我正在使用带有MongoEngine的Flask创建一个应用程序来连接到MongoDB。 我的文件夹结构如下所示:

app/
    __init__.py
    mod_users/
        __init__.py
        constants.py
        forms.py
        models.py 
        views.py
    mod_games/
        __init__.py
        constants.py
        forms.py
        models.py 
        views.py

让我们说我的用户和游戏模型如下:

mod_users / models.py

class User(db.Document):
    email = db.EmailField()
    username = db.StringField()
    password = db.StringField()

mod_games / models.py

from app.mod_users.models import User

class Game(db.Document):
    title = db.StringField()
    creator = db.ReferenceField(User, reverse_delete_rule=db.CASCADE)
    likes_count = db.IntField()

现在,我的问题是我希望用户拥有他喜欢的游戏列表。但是我不能使用引用字段,因为我必须导入Game才能创建循环导入。

这不会起作用:

from app.mod_games.models import Game

class User(db.Document):
    email = db.EmailField()
    username = db.StringField()
    password = db.StringField()
    liked_games = db.ListField(
        db.ReferenceField(Game, reverse_delete_rule=db.PULL)
    )

我考虑过在每个游戏中存储喜欢它的用户列表,然后在游戏中添加一个可以检索的静态方法 给定用户的喜欢游戏列表,但这似乎不是一种干净有效的解决方法。

3 个答案:

答案 0 :(得分:1)

M:通过关联类

建模的N个关系

游戏和用户之间存在关系,任何数量的用户都可以喜欢一个游戏,一个用户可以喜欢任意数量的游戏。

这是典型的M:N关系,这是由关联类建模的(将其作为类建模规则)。

班级应该有:

  • 对用户的引用
  • 参考游戏
  • 此特定关系的任何其他属性,例如这个游戏使用了多少颗星。

元组用户 - 游戏必须是唯一的。

定义此类类时,可以从User和Game模块导入。

用户和游戏不得导入此关联类(否则您将再次进入循环引用问题)

答案 1 :(得分:1)

虽然你有一个答案--MongoEngine确实可以满足这个要求,因为你可以将类的字符串名称传递给参考字段,例如:

class User(db.Document):
    email = db.EmailField()
    username = db.StringField()
    password = db.StringField()
    liked_games = db.ListField(
        db.ReferenceField('Game', reverse_delete_rule=db.PULL)
    )

答案 2 :(得分:0)

mentioned before一样,您可以将模型的字符串名称传递给参考字段。这是避免循环导入的第一件事:

class User(db.Document):
    company = db.ReferenceField('Company')

但是,当您拥有使用某种模型的方法时,例如,汇总一些数据,上述方法无济于事-您仍然可能会遇到循环进口问题。要解决此问题,请尝试使用get_document函数。参见下面的示例。

from mongoengine.base.common import get_document as get_model

class User(db.Document):
    # fields definition omitted

    def get_games(self):
        Game = get_model('Game')
        games = Game.objects.filter(user=self.pk)
        # some code here