【问题标题】:Django: do I need to make a caching method?Django:我需要做一个缓存方法吗?
【发布时间】:2016-07-06 10:54:38
【问题描述】:

我有一个模型Person,在那里我做了很多相同类型的查询。例如,我可能会多次询问同一页面中的“头像”。

正如你在我的代码中看到的,我已经实现了一种“排序”的缓存:将结果放入一个数组中,然后,如果这个数组中有一个键,则返回结果。

class Personne(BaseModel):

    def __init__(self, *args, **kwargs):
        # Mise en place de cache :
        self.cache = {}
        super(Personne, self).__init__(*args, **kwargs)

    def url_profile_picture(self):
        # gestion du cache :
        retour = self.cache.get('profile_picture')
        if retour:
            return retour
        a = PersonnePhoto.objects.filter(personne=self,
                                         photo_type=PersonnePhoto.PHOTO_PROFIL)
        if len(a):
            a = reverse('url_public', kwargs={'path': a[0].photo})
        else:
            a = staticfiles.static('img/no-picture-yet.png')
        self.cache['photo_profil'] = a
        return a

我想知道(因为我是 Django 新手)如果 Django 已经拥有自己的缓存系统是否有用。我的意思是:我的查询PersonnePhoto.objects.filter(...)会一直访问数据库->我肯定需要自己的缓存,还是被Django缓存->没用自己写缓存方法?

【问题讨论】:

  • 我看不出 Django 或任何软件组件如何缓存诸如此类的任意查询。没有办法判断Personne 的 URL 自上次读取后是否已更改,除非查询数据库。事实上,除非这个属性是只读的,否则你应该考虑你当前的缓存尝试在那种情况下是否会失效。
  • 另一件要考虑的事情,假设这个模型与“personne”和存储的 FileField 相关,你可以简单地使用 ORM 来获取 url,它应该缓存结果以在单个页面上多次使用。但这将取决于您如何真正使用此属性(我们无法从发布的代码中看到)。

标签: python django caching django-models


【解决方案1】:
from django.core.cache import cache

在您的模型中,我建议如下:

def url_profile_picture(self):
    # gestion du cache :
    retour = cache.get('profile_picture_%s' % self.pk)
    if retour:
        return retour

    else:
        a = PersonnePhoto.objects.filter(personne=self,
                                      photo_type=PersonnePhoto.PHOTO_PROFIL)
        if len(a):
            a = reverse('url_public', kwargs={'path': a[0].photo})
        else:
            a = staticfiles.static('img/no-picture-yet.png')

        cache.set('profile_picture_%s' % self.pk, a)

        return a

可以在这里阅读更多关于 django 缓存的信息:https://docs.djangoproject.com/en/1.9/topics/cache/

编辑:然后在您的个人资料区域中,您可以在上传图片时清除缓存以使其显示更快。

【讨论】:

  • 注意:如果您经常使用该属性,我的解决方案会大量调用缓存系统,因此对于这么小的值,Ludwi 的答案可能会更好。
【解决方案2】:

我想你正在寻找the cached_property decorator。它的行为与您为自己推出的解决方案完全相同(区别在于 url_profile_picture 现在是一个属性):

from django.utils.functional import cached_property

class Personne(BaseModel):
    @cached_property 
    def url_profile_picture(self):
        a = PersonnePhoto.objects.filter(personne=self,
                                         photo_type=PersonnePhoto.PHOTO_PROFIL)
        if len(a):
            a = reverse('url_public', kwargs={'path': a[0].photo})
        else:
            a = staticfiles.static('img/no-picture-yet.png')
        return a

【讨论】:

  • 我认为这个缓存会存在很短的时间并且不会提供任何真正的好处(只有对象存在的时间,这对于单个页面加载来说很好,并且可能不需要它反正)。我将添加一个我使用过的sudo代码解决方案
  • @warath-coder 我完全不同意你的观点。 OP 显示的解决方案具有相同的属性(仅与对象一样长)并且他没有要求更改它,但前提是 Django 已经涵盖了该属性 - 确实如此,前提是有人使用 @cached_property 装饰器.他还明确表示“我可能会多次询问“个人资料图片”在同一页面中”,这正是创建 @cached_property 的用例,它提供了真正的好处在这种情况下。
  • 当然...当您有 1,000 多个页面加载时,您将对数据库进行 1,000 多个调用。所以,正如我所说,对于单个页面加载,您是正确的,这会很好,但在大容量网站上,它不会。
  • 哦,来一个。我根据需要使用不同类型的缓存。这很明显,不是吗?我确定您并不是建议您需要为一切 使用外部缓存。我在问题中没有看到 OP 正在寻找(或特别需要)和外部缓存的迹象。
  • @cached_property 是 Django 的一部分,因为它在一个请求中需要多次调用同一个方法时非常有用。 OP 表示这正是他正在做的事情,他推出了自己的解决方案,其行为与@cached_property 完全相同。 OP 询问这种缓存是否内置在 Django 中。答案是肯定的,有,它叫@cached_property,但你需要启用它。这就是对the的直接答案,而这正是我所说的。这对我来说是 EOT。
猜你喜欢
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 2010-11-20
  • 2010-11-06
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多