首页 > 解决方案 > Mongoengine @property 导致多次加载用户模型

问题描述

我通过@property 函数向我的用户模型添加了几个属性。基本上它所做的是调用缓存以检索一些不在数据库中的数据。

我发现,当我从flask html 模板调用@property 设置的属性之一时,属性方法会再次执行。

我将尝试解释它:

首先,用户模型(它有更多字段,但这不相关):

class User(db.Document,UserMixin):
creation_date = db.DateTimeField(required=True, default=datetime.now)
activation_code = db.StringField()
email = db.EmailField(required=True,unique=True)
name = db.DictField(required=True)
password = db.StringField(required=True)

@property
def score(self):
    x = redis_userScore.get(str(self.id))
    return x

@property
def questionCount(self):
    print('Thomas')
    x = redis_questionsPerUser.zscore('questions', str(self.id))
    return x

现在我向@property 添加了一个简单的打印语句来测试它运行了多少次。

在一个空模板中,这个零。但是现在在我的模板中,我例如调用:

{{ (current_user.score) }}

现在我看到这个打印语句正在打印。现在我更改模板,它看起来像这样:

{{ (current_user.score) }}
{{ (current_user.score) }}

打印语句有两次!该函数已运行两次。

这告诉我,每次我在模板中使用 @property 下的属性之一时,它都会运行。这会使应用程序不必要地变慢。我曾期望属性的行为与“正常”属性相同,例如姓名、电子邮件等。因此,当我加载 current_user 时,会添加属性并且无需再次运行即可使用。

如何将额外的字段添加到模型中,而不是在每次调用时都运行它?就像它适用于其他“正常”字段一样。

提前致谢!

标签: pythonflaskmongoengine

解决方案


python 的@property 只是方便的getter,默认情况下它们不缓存返回值。可以使用以下模式来缓存返回值。

class User():
    def __init__(self):
        self._score = None

    @property
    def score(self):
        if self._score is None:
            self._score = self.get_from_cache()
        return self._score

    def get_from_cache(self):
        print(“fake call to cache”)
        return 1000

这里的示例是普通的 python,但是将其应用于 MongoEngine Document 类非常相似(构造函数会有所不同,因为您需要调用 super)


推荐阅读