【问题标题】:Is it possible to disable caching from Django admin pages?是否可以从 Django 管理页面禁用缓存?
【发布时间】:2019-03-15 14:40:23
【问题描述】:

[附加信息]

我要求一种方法来禁用站点范围内的缓存。 这可能有点矫枉过正,因为我所需要的只是一种能够查看页面的最新版本的方法,而数据库或生成它的程序有已修改。

普遍认为在运行时修改设置是一个非常糟糕的主意

所以,一些想法:清除缓存可能会起作用,就像发送标志以指定我不想看到缓存的版本,或指定来自我的 IP 地址的请求不应看到缓存页面

[原问题]

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

每次我处理它时,我都会修改 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 中某处的复选框?

【问题讨论】:

  • 我开始认为我需要维护一个单独的站点进行开发。
  • 也许在您的站点部署的机器上放置一个脚本(shell),在某个动作上执行该脚本并修改设置文件?
  • 也许使用 django-constance 从管理员那里设置一个动态布尔标志,然后根据标志值创建一个行为类似于 DummyCache 或 FileBasedCache 的自定义缓存后端?
  • 远射,但github.com/jazzband/django-configurations 让您有机会在 django 设置中使用环境变量作为值。您可以在管理员中创建一个按钮来更改环境变量并重新启动服务器。
  • “我开始认为我需要维护一个单独的站点来进行开发。”——你真的,真的应该。或者,实际上,您需要maintain a separate site for production, since your current "production" site is really a development site

标签: python django caching django-admin


【解决方案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

【讨论】:

  • 我会稍微修改一下解决方案……一想到有一个不受保护的地址会影响缓存,我就会不寒而栗。不过,这项技术正是我所需要的。非常感谢。
  • 不客气!附带说明:视图已经受到保护,防止未经授权的访问 - 如果发出请求的用户不是超级用户,则会引发异常并且根本不影响缓存
  • 所以我可以将其添加到常规默认视图中,超级用户将始终获得最新版本。我不需要网址。有趣的是,当您拥有更多知识时,事情会变得多么简单。
  • 我理解你的意思......但是虽然这看起来很方便,但你也失去了一点控制。首先,请注意,当超级用户进入“默认页面”时,所有用户都会受到影响,因为缓存在系统范围内无效。其次,每次调用默认视图时(当您使用其他视图时永远不会),即使在不必要的情况下,您总是会遇到缓存失效。这听起来很像不受控制的副作用。即使在这种情况下这不是什么大问题,它也不是最安全的解决方案......
  • ... 我仍然相信缓存失效的特定 url 更合适有效。使用该地址在浏览器中打开一个新选项卡,使用您的网站内容,完成编辑后刷新“clear_cache 页面”......就是这么简单;)
【解决方案2】:

我最终做了什么:

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. 该标志已添加到页面标题,因此您可以确保看到的是最新版本。

【讨论】:

  • 显然,添加到标题的标志是特定于我的 CMS 程序的。
  • 您可以更进一步,使用get_urls() 将此网址放在ModelAdmins 之一中,然后将其包装在admin_view() 中,这样只有登录的管理员用户才能访问此功能。
【解决方案3】:

使用单独的网站进行开发总是一件好事。 尽管如此,能够在生产站点上轻松禁用缓存可能会带来一些额外的好处:

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

我相信这可以通过提供精简的自定义缓存后端的少量代码成功解决。

基本上:

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

以下 POC 已在一个小型测试项目中进行了检查,结果为阳性。

首先,编写充当 FileBasedCache 或 DummyCache 的“代理”类:

文件'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

【讨论】:

  • 这看起来是一个可靠的解决方案,但我现在没有时间或专业知识来使用它。当我在整个项目中更进一步并且需要更强大的解决方案时,我会回到它。我在 Django 方面真的非常缺乏经验,任何看过我项目的人都可能会畏缩。
【解决方案4】:

您可以使用django-admin-caching 模块。首先在你的 bash 终端中安装它:

pip install django-admin-caching

安装后,将这段代码添加到您的settings.py,以便它自动注册:

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

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

【讨论】:

  • 看起来这是用于缓存管理页面,而不是主站点。我弄错了吗?
【解决方案5】:

主请求可以使用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()

【讨论】:

    猜你喜欢
    • 2011-07-08
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 2010-12-10
    • 2017-05-31
    • 2010-09-21
    • 1970-01-01
    相关资源
    最近更新 更多