如何memoize的上Django的模型对象昂贵的计算?(How do I memoize expe

2019-08-17 09:00发布

我有包含JSON对象我的用户配置对象上几个文本字段列。 我还限定的设定器/吸气剂属性它封装用于序列化和反序列化JSON成蟒数据结构的逻辑的每一列。

该数据的性质将确保自己在单个请求中被访问由视图和模板逻辑多次。 为了节省成本的反序列化,我想memoize的在读蟒蛇数据结构,无效直接写的财产或从模型对象保存信号。

在哪里/我如何保存笔记? 我很担心使用实例变量,因为我不知道后面怎么任何特定用户配置由查询实例化的魔力。 是__init__使用安全,或是否需要通过检查备忘录属性的存在hasattr()在每个读?

这是我目前执行的一个例子:

class UserProfile(Model):
    text_json = models.TextField(default=text_defaults)

    @property
    def text(self):
        if not hasattr(self, "text_memo"):
            self.text_memo = None
        self.text_memo = self.text_memo or simplejson.loads(self.text_json)
        return self.text_memo
    @text.setter
    def text(self, value=None):
        self.text_memo = None
        self.text_json = simplejson.dumps(value)

Answer 1:

您可能会感兴趣的内置Django的装饰django.utils.functional.memoize

Django使用这个缓存像URL解析昂贵的操作。



Answer 2:

一般情况下,我使用这样的模式:

def get_expensive_operation(self):
    if not hasattr(self, '_expensive_operation'):
        self._expensive_operation = self.expensive_operation()
    return self._expensive_operation

然后,您使用get_expensive_operation方法来访问数据。

然而,你的具体情况,我认为你是在轻微错误的方式接近这一点。 你需要做的,当模型首先从数据库加载反序列化,序列化和只会在保存。 然后,你可以每次只需要访问属性作为标准的Python字典。 您可以通过定义一个定制JSONField型,继承models.TextField,这将覆盖为此to_pythonget_db_prep_save

事实上其他人已经做到了:看这里 。



Answer 3:

对于类方法,你应该使用django.utils.functional.cached_property

由于上一类方法的第一个参数是selfmemoize将保持对对象的引用,你却把它甚至在走功能的结果。 这可以通过防止垃圾收集器从清理过时对象导致内存泄漏。 cached_property原来丹尼尔的建议为装饰。



文章来源: How do I memoize expensive calculations on Django model objects?