如何让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
相关产品推荐
相关产品推荐

