我如何验证Django @cached_property正在工作(缓存)?

inn6fuwd  于 2022-11-26  发布在  Go
关注(0)|答案(3)|浏览(123)

在下面的例子中,我有一些问题。

示例

from django.utils.functional import cached_property

class Product(models.Model):
    class ProductType(models.TextChoices):
        PRODUCT = 'PRODUCT', _('Product')
        LISTING = 'LISTING', _('Listing')

    my_model = models.ForeignKey(MyModel, on_delete=models.CASCADE, related_name='products')
    product_type = models.CharField(max_length=7, choices=ProductType.choices)

class MyModel(models.Model):
    ...
    
    @cached_property
    def listing(self):
        return self.products.get(product_type=Product.ProductType.LISTING)

问题

  1. listing属性是否被缓存在MyModel对象上?我这样问是因为它正在访问一个查询集的.get(),这有更大的影响。
    例如:
instance = MyModel()
instance.listing # hits db
instance.listing # gets from cache?

1.我如何设置一个场景来检查和验证instance.listing的缓存是否确实发生了?我阅读了instance.listing.__dict____dict__方法,但没有注意到任何具体的内容。

mnemlml8

mnemlml81#

如果您阅读了这个装饰器的源代码https://docs.djangoproject.com/en/4.0/_modules/django/utils/functional/#cached_property,您会发现您可能在错误的位置检查了它。listing将缓存在示例本身上,这意味着您需要检查instance.__dict__

8yoxcaq7

8yoxcaq72#

我给@Sardorbek Imomaliev颁发了一个答案,因为它为我指明了正确的方向。为了让任何偶然发现这个问题的人清楚起见,以下是我的发现。
1.列表属性是否缓存在MyModel对象上?我这样问是因为它正在访问一个queryset的.get(),这有更大的含义。
答:是的。但是,如果缓存对象的属性发生变化,这些变化在缓存对象中是不可见的。例如:如果价格从$4变为$5,则缓存的属性仍将显示$4。
1.如何设置一个场景来检查和验证instance.listing的缓存是否确实发生了?
答:

>>> inst = MyModel.objects.first()
>>> inst.__dict__.keys()
dict_keys(['_state', 'id', 'user_id', 'title', 'slug'])
>>> inst.listing
<Listing: Some Listing Instance>
>>> inst.__dict__.keys()
dict_keys(['_state', 'id', 'user_id', 'title', 'slug', 'listing'])

1.额外好处:如果它不是@cached_property,而只是一个普通的@property,它看起来会是什么样子?
答案:'listing'不会添加到inst.__dict__

>>> inst = MyModel.objects.first()
>>> inst.__dict__.keys()
dict_keys(['_state', 'id', 'user_id', 'title', 'slug'])
>>> inst.listing
<Listing: Some Listing Instance>
>>> inst.__dict__.keys()
dict_keys(['_state', 'id', 'user_id', 'title', 'slug'])
8aqjt8rx

8aqjt8rx3#

要删除缓存的属性,您可以使用del inst.listing。因此,只要产品型号发生更改,您基本上就可以使用信号删除此属性缓存

相关问题