Repository: django-cms/django-cms

Issue:
Plugin is always cached
I have a contact form in a plugin. If i set `cache = False` in the plugin, it gets cached anyway and it creates all sorts of problems.

Disabling the plugin cache with `CMS_PLUGIN_CACHE = False` works, but setting `CMS_PLACEHOLDER_CACHE = False` does not. It gives me:
UnboundLocalError 
local variable 'cache' referenced before assignment
cms/plugin_rendering.py in render_placeholder, line 174



Discussion:

Resolving patch:
diff --git a/cms/plugin_rendering.py b/cms/plugin_rendering.py
--- a/cms/plugin_rendering.py
+++ b/cms/plugin_rendering.py
@@ -121,8 +121,8 @@ def render_placeholder(placeholder, context_to_copy, name_fallback="Placeholder"
         processors = (toolbar_plugin_processor,)
     else:
         processors = None
+    from django.core.cache import cache
     if get_cms_setting('PLACEHOLDER_CACHE'):
-        from django.core.cache import cache
         cache_key = placeholder.get_cache_key(lang)
         if not edit and placeholder and not hasattr(placeholder, 'cache_checked'):
             cached_value = cache.get(cache_key)
@@ -170,7 +170,8 @@ def render_placeholder(placeholder, context_to_copy, name_fallback="Placeholder"
     context['placeholder'] = toolbar_content
     context['edit'] = edit
     result = render_to_string("cms/toolbar/content.html", context)
-    if placeholder and not edit and placeholder.cache_placeholder:
+
+    if placeholder and not edit and placeholder.cache_placeholder and get_cms_setting('PLACEHOLDER_CACHE'):
         cache.set(cache_key, result, get_cms_setting('CACHE_DURATIONS')['content'])
     context.pop()
     return result


Test patch:
diff --git a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py
--- a/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py
+++ b/cms/test_utils/project/pluginapp/plugins/caching/cms_plugins.py
@@ -1,9 +1,15 @@
 # -*- coding: utf-8 -*-
+from datetime import datetime
 from cms.plugin_base import CMSPluginBase
 
 
 class NoCachePlugin(CMSPluginBase):
     name = 'NoCache'
     module = 'Test'
-    render_plugin = False
+    render_plugin = True
     cache = False
+    render_template = "plugins/nocache.html"
+
+    def render(self, context, instance, placeholder):
+        context['now'] = datetime.now().microsecond
+        return context
diff --git a/cms/test_utils/project/templates/plugins/nocache.html b/cms/test_utils/project/templates/plugins/nocache.html
new file mode 100644
--- /dev/null
+++ b/cms/test_utils/project/templates/plugins/nocache.html
@@ -0,0 +1 @@
+$$${{ now }}$$$
\ No newline at end of file
diff --git a/cms/tests/cache.py b/cms/tests/cache.py
--- a/cms/tests/cache.py
+++ b/cms/tests/cache.py
@@ -4,11 +4,13 @@
 from cms.plugin_pool import plugin_pool
 from cms.test_utils.project.pluginapp.plugins.caching.cms_plugins import NoCachePlugin
 from cms.test_utils.testcases import CMSTestCase
+from cms.test_utils.util.context_managers import SettingsOverride
 from cms.test_utils.util.fuzzy_int import FuzzyInt
 from cms.toolbar.toolbar import CMSToolbar
 from django.core.cache import cache
 from django.db import connection
 from django.template import Template, RequestContext
+from django.conf import settings
 
 
 class CacheTestCase(CMSTestCase):
@@ -16,7 +18,6 @@ def tearDown(self):
         cache.clear()
 
     def test_cache_placeholder(self):
-        create_page
         template = Template("{% load cms_tags %}{% placeholder 'body' %}{% placeholder 'right-column' %}")
         page1 = create_page('test page 1', 'nav_playground.html', 'en',
                             published=True)
@@ -48,9 +49,23 @@ def test_cache_placeholder(self):
         rctx = RequestContext(request)
         with self.assertNumQueries(3):
             template.render(rctx)
+        page1.publish('en')
+        cache.clear()
+        exclude = [
+            'django.middleware.cache.UpdateCacheMiddleware',
+            'django.middleware.cache.FetchFromCacheMiddleware'
+        ]
+        middleware = [mw for mw in settings.MIDDLEWARE_CLASSES if mw not in exclude]
+        with SettingsOverride(CMS_PAGE_CACHE=False, MIDDLEWARE_CLASSES=middleware):
+            with self.assertNumQueries(FuzzyInt(14, 18)):
+                self.client.get('/en/')
+            with self.assertNumQueries(FuzzyInt(7, 11)):
+                self.client.get('/en/')
+            with SettingsOverride(CMS_PLACEHOLDER_CACHE=False):
+                with self.assertNumQueries(FuzzyInt(9, 13)):
+                    self.client.get('/en/')
 
     def test_no_cache_plugin(self):
-        create_page
         template = Template("{% load cms_tags %}{% placeholder 'body' %}{% placeholder 'right-column' %}")
         page1 = create_page('test page 1', 'nav_playground.html', 'en',
                             published=True)
@@ -77,14 +92,17 @@ def test_no_cache_plugin(self):
         with self.assertNumQueries(1):
             template.render(rctx)
         add_plugin(placeholder1, "NoCachePlugin", 'en')
-
+        page1.publish('en')
         request = self.get_request('/en/')
         request.current_page = Page.objects.get(pk=page1.pk)
         request.toolbar = CMSToolbar(request)
         template = Template("{% load cms_tags %}{% placeholder 'body' %}{% placeholder 'right-column' %}")
         rctx = RequestContext(request)
         with self.assertNumQueries(4):
-            template.render(rctx)
+            render = template.render(rctx)
+        with self.assertNumQueries(FuzzyInt(14, 18)):
+            response = self.client.get('/en/')
+            resp1 = response.content.decode('utf8').split("$$$")[1]
 
         request = self.get_request('/en/')
         request.current_page = Page.objects.get(pk=page1.pk)
@@ -92,7 +110,12 @@ def test_no_cache_plugin(self):
         template = Template("{% load cms_tags %}{% placeholder 'body' %}{% placeholder 'right-column' %}")
         rctx = RequestContext(request)
         with self.assertNumQueries(4):
-            template.render(rctx)
+            render2 = template.render(rctx)
+        with self.assertNumQueries(FuzzyInt(10, 14)):
+            response = self.client.get('/en/')
+            resp2 = response.content.decode('utf8').split("$$$")[1]
+        self.assertNotEqual(render, render2)
+        self.assertNotEqual(resp1, resp2)
 
         plugin_pool.unregister_plugin(NoCachePlugin)
 
diff --git a/cms/tests/toolbar_pool.py b/cms/tests/toolbar_pool.py
--- a/cms/tests/toolbar_pool.py
+++ b/cms/tests/toolbar_pool.py
@@ -31,7 +31,6 @@ def test_register_type(self):
         self.assertRaises(ImproperlyConfigured, self.pool.register, object)
 
     def test_register_order(self):
-        print(self.pool.toolbars)
         self.pool.register(TestToolbar)
         self.pool.register(CMSToolbar)