Python Django REST框架&;Django模型实例的生命周期
我有一个django rest框架应用程序,目前在我的模型和序列化程序中大量使用计算属性。对于(过于简化的)示例: 型号.pyPython 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): 类元: 模特=人 字段=(“名”、“姓”、“全名”) 我
班级人员(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)
谢谢你周到的答复。非常有趣。我会等一会儿再接受,看看是否还有其他想法。