You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Django模型的计算属性仅执行一次并返回结果?

Django模型计算属性单次执行缓存实现方法

以下几种方案可以实现计算属性仅执行一次,后续直接返回缓存结果:

方案一:手动实例变量缓存

直接通过实例的私有变量存储计算结果,后续调用优先读取缓存:

import datetime
from django.db import models

class Company_Car(models.Model):
    @property
    def days_left(self):
        # 检查是否已缓存结果
        if hasattr(self, '_days_left_cache'):
            return self._days_left_cache
        
        print("RUNNED PROPERTY")
        result = None
        if self.date_valid is not None and self.date_valid >= datetime.datetime.now().date():
            result = (self.date_valid - datetime.datetime.now().date()).days
        
        # 将结果存入实例缓存
        self._days_left_cache = result
        return result
    
    added            = models.DateTimeField(auto_now_add=True)
    status           = models.BooleanField(default=True)
    company          = models.ForeignKey(Company, on_delete=models.DO_NOTHING)
    date_valid       = models.DateField(null=True, blank=True)

特点:

  • 逻辑直观,完全手动控制缓存生命周期
  • 若date_valid字段在运行时被修改,可通过del car._days_left_cache手动清除缓存,触发重新计算

方案二:使用Django内置cached_property装饰器

Django提供了专门用于模型属性缓存的cached_property,无需手动处理缓存变量:

import datetime
from django.db import models
from django.utils.functional import cached_property

class Company_Car(models.Model):
    @cached_property
    def days_left(self):
        print("RUNNED PROPERTY")
        if self.date_valid is not None and self.date_valid >= datetime.datetime.now().date():
            return (self.date_valid - datetime.datetime.now().date()).days
        return None
    
    added            = models.DateTimeField(auto_now_add=True)
    status           = models.BooleanField(default=True)
    company          = models.ForeignKey(Company, on_delete=models.DO_NOTHING)
    date_valid       = models.DateField(null=True, blank=True)

特点:

  • Django官方实现,适配模型场景,用法简洁
  • 缓存自动管理,第一次调用计算后缓存结果
  • 需重新计算时,执行del car.days_left即可清除缓存

方案三:使用functools.lru_cache

通过Python标准库的缓存装饰器实现,但需为模型实例添加哈希方法:

import datetime
from functools import lru_cache
from django.db import models

class Company_Car(models.Model):
    # 定义哈希方法,以主键作为唯一标识
    def __hash__(self):
        return hash(self.pk)
    
    @property
    @lru_cache(maxsize=None)
    def days_left(self):
        print("RUNNED PROPERTY")
        if self.date_valid is not None and self.date_valid >= datetime.datetime.now().date():
            return (self.date_valid - datetime.datetime.now().date()).days
        return None
    
    added            = models.DateTimeField(auto_now_add=True)
    status           = models.BooleanField(default=True)
    company          = models.ForeignKey(Company, on_delete=models.DO_NOTHING)
    date_valid       = models.DateField(null=True, blank=True)

特点:

  • 依赖Python标准库,适用于非Django场景也能复用
  • 需要手动实现__hash__方法,确保实例可被缓存识别
  • 相比cached_property,在模型序列化或传递时需额外注意哈希逻辑的稳定性

推荐方案

优先选择方案二,因为它是Django专为模型属性缓存设计的工具,无需额外编写缓存管理逻辑,适配性和易用性最佳。

内容的提问来源于stack exchange,提问作者Yuretz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:33:18