Python Django REST框架&;Django模型实例的生命周期

Python Django REST框架&;Django模型实例的生命周期,python,django,caching,django-rest-framework,Python,Django,Caching,Django Rest Framework,我有一个django rest框架应用程序,目前在我的模型和序列化程序中大量使用计算属性。对于(过于简化的)示例: 型号.py 班级人员(models.Model): first_name=models.CharField() last_name=models.CharField() @财产 全名(自我): 返回名字+姓氏 序列化程序.py 类PersonSerializer(serializers.ModelSerializer): 类元: 模特=人 字段=(“名”、“姓”、“全名”) 我

我有一个django rest框架应用程序,目前在我的模型和序列化程序中大量使用计算属性。对于(过于简化的)示例:

型号.py

班级人员(models.Model):
first_name=models.CharField()
last_name=models.CharField()
@财产
全名(自我):
返回名字+姓氏
序列化程序.py

类PersonSerializer(serializers.ModelSerializer):
类元:
模特=人
字段=(“名”、“姓”、“全名”)
我对使用Django而不是
@property
感兴趣,希望能加快速度,因为这里计算的值一天不会改变超过一次

不过,我不确定是否会影响DRF返回JSON响应的速度。Django文件说:

@cached_属性装饰器缓存具有单个自参数作为属性的方法的结果。缓存的结果将保持实例的时间,因此如果传递实例并随后调用函数,则将返回缓存的结果


所以我想知道Django模型实例的生命周期是什么?它是否会在每次调用DRF视图时创建?如果是这样,有没有其他方法可以实现我的目标?

这个
@cached_属性
decorator似乎可以处理内存中的一个实例,类似于查询集的缓存方式。这里有一个小例子来说明我的意思:

# Model that stores two numbers and returns their sum (slowly)
class MyModel(models.Model):
    a = models.IntegerField()
    b = models.IntegerField()

    @cached_property
    def sum(self):
        time.sleep(10)
        return a + b

my_model = MyModel(a=1, b=2)
my_model.save()
print(my_model.sum) # This will take 10 seconds because of the sleep
print(my_model.sum) # This will return instantly because the result is cached and it doesn't need to execute the properties code

my_model_again = MyModel.objects.first()  # Lets fetch that model again from the database.
print(my_model_again.sum)  # This will take 10 seconds because of the sleep

# We can pass the instance around into other functions, and because it is still the same object it will leverage the cached property
def double_sum(instance):
    return instance.sum + instance.sum
print(double_sum(my_model_again))  # This will print almost instantly
在这个例子中,我使用睡眠来模拟一个冗长的或计算代价高昂的计算

虽然
my\u model
my\u model\u
表示相同的数据库行,但它们在内存中是不同的实例。您必须传递实例以利用缓存属性

如果希望缓存在该对象的所有实例之间保持,可以将结果存储在数据库中,并每24小时使其无效。下面是一个使用数据库的简单示例:

class MyModel(models.Model):
    a = models.IntegerField()
    b = models.IntegerField()
    cached_sum = models.IntegerField(default=None, null=True, blank=True)
    cached_sum_timestamp = models.DateTimeField()

    @property
    def sum(self):
        # If the sum has been calculated in the last 24 hours, return the cached sum, otherwise recalculate 
        if (
            self.cached_sum 
            and self.cached_sum_timestamp
            and self.cached_sum_timestamp > (timezone.now() - timezone.timedelta(days=1)
        ):
            return self.cached_sum

        time.sleep(10)
        self.cached_sum = self.a + self.b
        self.cached_sum_timestamp = timezone.now()
        self.save(update_fields=("cached_sum", "cached_sum_timestamp"))

        return self.cached_sum
但是,您可能还希望在更改模型时使缓存无效。。。这是可能的,但它变得有点困难。缓存失效很难正确处理。下面是一个在实例字段更改时使缓存无效的非常简单的示例:

class MyModel(models.Model):
    a = models.IntegerField()
    b = models.IntegerField()
    cached_sum = models.IntegerField(default=None, null=True, blank=True)

    @property
    def sum(self):
        if self.cached_sum:
            return self.cached_sum

        time.sleep(10)
        self.cached_sum = self.a + self.b
        self.save(update_fields=("cached_sum", ))
        return self.cached_sum

    def save(self, *args, **kwargs):
        if self.pk:  # Compare the object we're saving with whats in the database, and if the cache should be invalidated then set cached_sum to None
            db_obj = MyModel.objects.get(pk=self.pk)
            if db_obj.a != self.a or db_obj.b != self.b:
                self.cached_sum = None
        else:
            # It would be nice to cache this when we create the object?
            if self.cached_sum is not None:
                self.cached_sum = self.sum
        return super().save(*args, **kwargs)

谢谢你周到的答复。非常有趣。我会等一会儿再接受,看看是否还有其他想法。