oro*_*aki 5 python django attributes caching properties
在以下示例中,cached_attr用于related_spam在调用数据库昂贵的属性(在示例中)时获取或设置模型实例上的属性.在示例中,我cached_spam用来保存查询.我在设置和获取值时放置了print语句,以便我可以测试它.我通过将Egg实例传递到视图和视图中来测试它,并使用模型{{ egg.cached_spam }}上的其他方法Egg调用cached_spam他们自己.当我完成并测试它时,Django的开发服务器中的shell输出显示属性缓存被错过了好几次,并成功获得了几次.这似乎是不一致的.使用相同的数据,当我进行小的更改(只需更改print语句的字符串)并刷新(使用所有相同的数据)时,会发生不同数量的未命中/成功.这是怎么发生的?这段代码不正确或有问题吗?
class Egg(models.Model):
... fields
@property
def related_spam(self):
# Each time this property is called the database is queried (expected).
return Spam.objects.filter(egg=self).all() # Spam has foreign key to Egg.
@property
def cached_spam(self):
# This should call self.related_spam the first time, and then return
# cached results every time after that.
return self.cached_attr('related_spam')
def cached_attr(self, attr):
"""This method (normally attached via an abstract base class, but put
directly on the model for this example) attempts to return a cached
version of a requested attribute, and calls the actual attribute when
the cached version isn't available."""
try:
value = getattr(self, '_p_cache_{0}'.format(attr))
print('GETTING - {0}'.format(value))
except AttributeError:
value = getattr(self, attr)
print('SETTING - {0}'.format(value))
setattr(self, '_p_cache_{0}'.format(attr), value)
return value
Run Code Online (Sandbox Code Playgroud)
就你的代码而言,你的代码没有任何问题.问题可能不在那里,而在于你如何使用该代码.
要实现的主要是模型实例没有标识.这意味着如果你在某个地方实例化一个Egg对象,而在其他地方实例化另一个,即使它们引用相同的底层数据库行,它们也不会共享内部状态.因此,调用cached_attr一个不会导致缓存在另一个中填充.
例如,假设您有一个带有ForeignKey to Egg的RelatedObject类:
my_first_egg = Egg.objects.get(pk=1)
my_related_object = RelatedObject.objects.get(egg__pk=1)
my_second_egg = my_related_object.egg
Run Code Online (Sandbox Code Playgroud)
这里my_first_egg和my_second_egg两者都引用pk 1的数据库行,但它们不是同一个对象:
>>> my_first_egg.pk == my_second_egg.pk
True
>>> my_first_egg is my_second_egg
False
Run Code Online (Sandbox Code Playgroud)
因此,填充缓存my_first_egg不会填充它my_second_egg.
而且,当然,对象不会在请求中持续存在(除非它们是专门设置为全局的,这很可怕),因此缓存也不会持久存在.