【问题标题】:Django 1.11: disable cache for authentificated usersDjango 1.11:为经过身份验证的用户禁用缓存
【发布时间】:2020-11-04 20:35:41
【问题描述】:

我们有一个用 python 2.7 和 django 1.11 编写的遗留应用程序(并且没有要迁移的资源)。它还使用grappelli 进行授权。我们尝试为某些页面添加Edit 链接(每个页面都显示Round 对象的详细信息),这些链接应该只对授权用户可见有权编辑回合(@987654327 @ 在grappelli Web 界面中)。在模板中,权限检查如下:

{% if perms.round.can_change_round %}
    &emsp;<a href="{{link_to_change_round}}" class="stuff-only-link">{% trans 'Edit' %}</a>
{% endif %}

当以下事件在很短的时间间隔内发生时,就会出现问题:

  1. 有权编辑回合的用户访问页面 - 并看到 Edit 链接。
  2. 无权编辑回合的用户(例如匿名用户)访问相同的页面 - 并且还看到了链接!

相关设置 (settings.py) 是:

CACHES = {
    'default': {
    #   'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    }
}

SOLO_CACHE = 'default'
SOLO_CACHE_TIMEOUT = 5*60

当我将缓存更改为dummy 时,问题就消失了。因此,完全禁用授权用户的缓存似乎是一个明显的解决方案。更准确地说:

a) 如果用户是匿名用户(大多数真实站点用户) - 请求的页面可以写入缓存,也可以从缓存中读取;

b) 如果用户被授权(大约 5-7 个用户) - 请求的页面不能写入缓存,也不能从缓存中读取。

我如何做到这一点?

【问题讨论】:

标签: python django caching authorization django-grappelli


【解决方案1】:

您可以对模板的缓存部分进行分段并从与用户相关的缓存部分中省略或根据分段变量状态将它们缓存为documented

【讨论】:

    【解决方案2】:

    非常感谢 @Melvin 提供的文档链接。经过一个小时的谷歌搜索,找到并改编了答案。代码是:

    编辑:最初,缓存是基于函数的。 因此,“/rounds/1”给出了与“/rounds/2”相同的(缓存的)值。 我们将完整的 URL 添加到缓存键以解决问题。

    # -*- encoding: utf-8 -*-
    '''
    Python >= 2.4
    Django >= 1.0
    
    Author: eu@rafaelsdm.com
    '''
    # https://djangosnippets.org/snippets/2524/
    # https://stackoverflow.com/questions/20146741/django-per-user-view-caching
    # https://stackoverflow.com/questions/62913281/django-1-11-disable-cache-for-authentificated-users
    
    from django.core.cache import cache
    
    def cache_per_user(ttl=None, prefix=None):
        '''Decorador que faz cache da view pra cada usuario
        * ttl - Tempo de vida do cache, não enviar esse parametro significa que o
          cache vai durar até que o servidor reinicie ou decida remove-lo 
        * prefix - Prefixo a ser usado para armazenar o response no cache. Caso nao
          seja informado sera usado 'view_cache_'+function.__name__
        * cache_post - Informa se eh pra fazer cache de requisicoes POST
        * O cache para usuarios anonimos é compartilhado com todos
        * A chave do cache será uma das possiveis opcoes:
            '%s_%s'%(prefix, user.id)
            '%s_anonymous'%(prefix)
            'view_cache_%s_%s'%(function.__name__, user.id)
            'view_cache_%s_anonymous'%(function.__name__)
        '''
        def decorator(function):
            def apply_cache(request, *args, **kwargs):
    
                # No caching for authorized users:
                # they have to see the results of their edits immideately!
    
                can_cache = request.user.is_anonymous() and request.method == 'GET'
    
                # Gera a chave do cache
                if prefix:
                    CACHE_KEY = '%s_%s'%(prefix, 'anonymous')
                else:
                    CACHE_KEY = 'view_cache_%s_%s_%s'%(function.__name__, request.get_full_path(), 'anonymous')
    
                if can_cache:
                    response = cache.get(CACHE_KEY, None)
                else:
                    response = None
    
                if not response:
                    print 'Not in cache: %s'%(CACHE_KEY)
                    response = function(request, *args, **kwargs)
                    if can_cache:
                        cache.set(CACHE_KEY, response, ttl)
                return response
            return apply_cache
        return decorator
    

    然后在views.py:

    from cache_per_user import cache_per_user as cache_page
    #...
    #
    #
    @cache_page(cache_duration)
    def round_detail(request, pk):
    

    【讨论】:

      猜你喜欢
      • 2012-07-24
      • 2015-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-15
      • 2016-11-30
      • 2012-05-08
      • 1970-01-01
      相关资源
      最近更新 更多