Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache not invalidated when using a PlaceholderField outside the CMS #6912 #6956

Merged
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Unreleased
* Fixed builds on RTD
* Remove debug print from apphook_reload
* Enforce use of coverage > 4 for python 3.8 support
* Fixed the cache not being invalidated when updating a PlaceholderField in a custom model
* Fixed 66622 bad Title.path in multilingual sites when parent slug is created or modified
* Fixed 6973 bag with unexpected behavior ``get_page_from_request``
* Temporarily pinned django-treebeard to < 4.5, this avoids breaking changes introduced
Expand Down
4 changes: 4 additions & 0 deletions cms/models/placeholdermodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,10 @@ def mark_as_dirty(self, language, clear_cache=True):
elif attached_model is StaticPlaceholder:
StaticPlaceholder.objects.filter(draft=self).update(dirty=True)

# Force to clear cache when attached model is not a Page or a StaticPlaceholder, otherwise cache is never invalidated when using PlaceholderField
elif clear_cache is False:
self.clear_cache(language)

def get_plugin_tree_order(self, language, parent_id=None):
"""
Returns a list of plugin ids matching the given language
Expand Down
53 changes: 53 additions & 0 deletions cms/tests/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,59 @@ def test_render_placeholder_cache(self):
text = content_renderer.render_placeholder(ph1, context)
self.assertEqual(text, "Other text")

def test_render_placeholderfield_cache_in_custom_model(self):
"""
Regression test for #6912

Assert that placeholder of a placeholderfield in custom model has its cache cleared correctly when mark_as_dirty is called in the admin
"""

invalidate_cms_page_cache()

# Create an instance of a custom model containing a placeholderfield
ex = Example1(char_1="one", char_2="two", char_3="tree", char_4="four")
ex.save()
ph1 = ex.placeholder

# Add a first plugin
test_plugin = add_plugin(ph1, "TextPlugin", "en", body="Some text")
test_plugin.save()

# Create a first request using render_placeholder to ensure that the content is equal to the first plugin content
request = self.get_request()
content_renderer = self.get_content_renderer(request)
context = SekizaiContext()
context["request"] = self.get_request()
text = content_renderer.render_placeholder(ph1, context, use_cache=True)
self.assertEqual(text, "Some text")

# Add a second plugin in the placeholder
test_plugin = add_plugin(ph1, "TextPlugin", "en", body="Some other text")
test_plugin.save()

# Clear plugins cache to ensure that cms.utils.plugins.get_plugins() will refetch the plugins
del ph1._plugins_cache

# Create a second request using render_placeholder to ensure that the content is still equal to the first plugin content as cache was not cleared yet
request = self.get_request()
content_renderer = self.get_content_renderer(request)
context = SekizaiContext()
context["request"] = self.get_request()
text = content_renderer.render_placeholder(ph1, context, use_cache=True)
self.assertEqual(text, "Some text")

# Mark placeholder as dirty as it is done in cms.admin.placeholderadmin file
ph1.mark_as_dirty("en", clear_cache=False)

# Create a last request to ensure that rendered content contains the two plugins content
request = self.get_request()
content_renderer = self.get_content_renderer(request)
context = SekizaiContext()
context["request"] = self.get_request()

text = content_renderer.render_placeholder(ph1, context, use_cache=True)
self.assertEqual(text, "Some textSome other text")


class PlaceholderCacheTestCase(CMSTestCase):
def setUp(self):
Expand Down