【问题标题】:Django Caching a User's profileDjango缓存用户的个人资料
【发布时间】:2023-03-22 23:07:01
【问题描述】:

我正在尝试缓存对 Django 配置文件对象的访问。我正在使用 django-redis-cache 来缓存这个项目中的数据。如果不存在,我正在使用 sn-p 自动创建配置文件。这是我正在做的事情的简化版本(没有缓存):

User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])

只要需要配置文件信息,就会访问 user.profile 属性。这可以按预期工作,但是,当我尝试缓存配置文件属性时,例如在图表 1 中,我仍然看到 SQL 查询(在 django-debug-toolbar 中)正在选择配置文件并且没有利用缓存。

具体来说,图表 2 中的 cache_object_list() 函数是一段代码,用于检查缓存值是否可用。如果是,则调用缓存键。如果没有,它会运行传递给它的查询(通过“查询”参数)并缓存结果。

cache_object_list() 打印“Hit”或“Miss”,表示缓存命中或未命中。刷新两次后,所有内容都被报告为命中(如预期的那样)。但是,django-debug-toolbar 仍然显示查询计数没有减少,并显示选择配置文件的查询。

对于如何确保 user.profile 在可用时提取配置文件的缓存版本,是否有人有任何建议?感谢阅读。

图表 1:myproject/myapp/models.py

def get_or_create_profile(u):
    return cache_utils.cache_single_object(
        "user_get_or_create_profile",
        u.id, UserProfile.objects.get_or_create(user=u)[0]) 

User.profile = property(lambda u: cache_utils.cache_single_object(
                    "user_get_or_create_profile", u.id,  
                     get_or_create_profile(u)))

图表 2:myproject/cache_utils.py

def cache_single_object(key_prefix, id, query, timeout=500):
    key = '%s_%s' % (key_prefix, id)
    object_list = cache.get(key, None)
    if object_list is None:
        print "Miss %s" % (key)
        object_list = query
        cache.set(key, object_list, timeout)
    else:
        print "Hit  %s" % (key)
    return object_list

图表 3:myproject/templates/mytemplate.py

<div>Example of what's in the template </div>
{{ myobject.owner.profile.bio }} 

【问题讨论】:

  • Exhibit 1 似乎使用了cache_utils.cache_single_object,而 Exhibit 2 显示了cache_object_list。是哪个?
  • 感谢指正。一个错字 - 我有 2 个函数基本上做同样的事情,但名称不同,并合并用于发布目的。我已经更正了示例,但缓存问题仍然存在。

标签: django caching properties redis profile


【解决方案1】:

我认为问题与您定义方法的方式有关....

User.profile = property(lambda u: cache_utils.cache_single_object(
                "user_get_or_create_profile", u.id,  
                 get_or_create_profile(u)))

当您访问配置文件属性时,您将始终调用 get_or_create_profile(u) 方法,该方法调用:

return cache_utils.cache_single_object(
    "user_get_or_create_profile",
    u.id, UserProfile.objects.get_or_create(user=u)[0]) 

拥有 UserProfile.objects.get_or_create(user=u) 即使您已经在缓存中拥有数据,每次都会创建您的查询。我认为您应该尝试使用一种 util 方法,在这种方法中,您每次调用时都不会评估查询。也许是这样的:https://stackoverflow.com/a/2216326/234304

【讨论】:

  • 感谢 Julian - 刚刚重新访问了这个缓存问题并看到了您的回复(抱歉回复晚了)。该解决方案基本上切断了视图生成的 1/3 查询。谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-07-16
  • 1970-01-01
  • 2014-10-13
  • 2021-09-04
  • 2020-12-14
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
相关资源
最近更新 更多