是否可以从Django管理页面禁用缓存?

时间:2019-03-15 14:40:24

标签: python django caching django-admin

[其他信息]

我要求一种禁用站点范围缓存的方法。 这可能是矫kill过正,因为当数据库或生成它的程序具有以下功能时,我所需要的就是一种能够查看页面的最新版本的方法已被修改。

强烈共识在运行时修改设置是一个非常糟糕的主意

因此,一些想法:清除缓存发送标志以指定我不想看到缓存的版本或指定从我的IP地址发出的请求应该看不到缓存的页面

[原始问题]

我在ozake.com有一个基于Django的网站,并且经常重写部分编程内容或更改页面内容。

每次进行此操作时,我都会修改settings.py以禁用缓存,这样我就可以实时查看自己的修改。

完成后,我将重新启用缓存。

我正在使用基于文件的缓存。这是settings.py的相关部分:

CACHES = {
  'default': {'BACKEND':
 #'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
  'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
  'LOCATION': '/var/www/mysite.com/cache',

在网站上工作时,我注释掉了最后两行,并取消了对虚拟缓存行的注释。

这意味着SSH进入站点,修改settings.py,在站点上工作,然后重新修改。

有什么办法可以使用admin.py将其放入/ admin中的复选框?

5 个答案:

答案 0 :(得分:1)

如果您只想随意使整个缓存无效,则可以创建一个简单的视图来做到这一点:

文件views.py

from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.views.decorators.cache import never_cache

@never_cache
def clear_cache(request):
    if not request.user.is_superuser:
        raise PermissionDenied
    cache.clear()
    return HttpResponse('Cache has been cleared')

文件urls.py

from django.urls import path
from . import views

urlpatterns = [
    ...
    path('clear_cache/', views.clear_cache),
]

然后使用您的浏览器调用它:

http://HOST/clear_cache

答案 1 :(得分:0)

使用单独的站点进行开发始终是一件好事。 尽管如此,可以轻松禁用生产站点上的缓存可能带来一些其他好处:

  • 调查与缓存相关的细微错误
  • 使用实际生产数据来衡量有效的性能提升

我相信,只需提供少量代码即可提供瘦的自定义缓存后端,即可成功解决此问题。

基本上:

  • Django在启动时实例化一个缓存“默认”对象,将其视为单例对象,并永久使用它
  • 在我们的自定义缓存后端中,我们将保留两个单独对象(“虚拟”和“基于文件”的缓存)的内部实例,并通过所需的接口方法仅公开其中的一个。
  • 这样,我们实际上充当了FileBasedCache或DummyCache的类代理
  • 我们可以轻松地通过变量控制哪个对象处于活动状态,从而在运行时切换行为,而无需重新启动Django

在一个小型测试项目中检查了以下POC,并获得了肯定的结果。

首先,编写行为类似于FileBasedCache或DummyCache的“ proxy”类:

文件“ project / mycache.py”:

from django.core.cache.backends.filebased import FileBasedCache
from django.core.cache.backends.dummy import DummyCache
from django.core.cache.backends.base import DEFAULT_TIMEOUT
from constance import config


class MyCache(DummyCache):

    def __init__(self, *args, **kwargs):
        self.dummy_cache = DummyCache(*args, **kwargs)
        self.file_cache = FileBasedCache(*args, **kwargs)

    def _active_cache(self):
        """
        Select either DummyCache or FileBasedCache based on configuration
        """
        return self.file_cache if config.CACHING_ENABLED else self.dummy_cache

    def add(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
        return self._active_cache().add(key, value, timeout, version)

    def get(self, key, default=None, version=None):
        return self._active_cache().get(key, default, version)

    def set(self, key, value, timeout=DEFAULT_TIMEOUT, version=None):
        self._active_cache().set(key, value, timeout, version)

    def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None):
        return self._active_cache().touch(key, timeout, version)

    def delete(self, key, version=None):
        self._active_cache().delete(key, version)

    def has_key(self, key, version=None):
        return self._active_cache().has_key(key, version)

    def clear(self):
        self._active_cache().clear()

并在项目设置中引用它,如下所示:

CACHES = {
    'default': {
        'BACKEND': 'project.mycache.MyCache',
        'LOCATION': '/var/www/mysite.com/cache,
    }
}

请注意,实际操作将根据 config.CACHING_ENABLED 的当前值委派给两个内部对象之一。代理模型中没有重新实现缓存逻辑。

最后,要从管理员(最简单的部分)控制切换标志,请为 django-constance (流行的应用程序,提供管理界面以编辑动态设置)定义布尔值'CACHING_ENABLED'

将此添加到项目的设置中:

INSTALLED_APPS = [
    ...
    'constance',
    'constance.backends.database',
]

CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend'
CONSTANCE_CONFIG = {
    'CACHING_ENABLED': (True, 'Set to False to disable caching'),
}

然后:

pip install django-constance[database]
python manage.py migrate

答案 2 :(得分:0)

您可以使用django-admin-caching模块。首先安装它,在您的bash终端中键入以下内容:

pip install django-admin-caching

安装后,将以下代码添加到settings.py中,以便其自动注册:

settings.INSTALLED_APPS = [
   #...
   'django_admin_caching',
   #...
]

这应该在django管理页面上启用缓存。

答案 3 :(得分:0)

我最终要做的事情:

from django.core.cache import cache

def PageView(request):
    ...
    if request.GET.get('clear') == 'cache':
        if request.user.is_superuser:
            title = request.GET.get('flag') + ' ' + title 
            cache.clear()
    ...
    return render(request, template, context)

所以现在我可以去 https://ozake.com/en/home?clear=cache&flag=sdf

如果我登录到管理页面,缓存将被清除。

两个注意事项:

  1. 此地址将被缓存,因此有必要每次更改标志字符串,以清除缓存。

  2. 该标志已添加到页面标题,因此您可以确保查看的是最新版本。

答案 4 :(得分:-1)

对于主要请求,您可以使用cache-table

另一种方法是使用中间件将接收到请求的IP与您可以存储在设置中的特定IP进行比较。像这样:

from django.http import HttpRequest
def get_user_ip(request):
    client_address = request.META['HTTPS_X_FORWARDED_FOR']
    if your_ip == client_address:
        save_user_ip()