Repository: django-cms/django-cms

Issue:
placeholder with plugins in language that don't exist anymore raises 500
def get_filled_languages(self):
        """
        Returns language objects for every language for which the placeholder
        has plugins.
        This is not cached as it's meant to eb used in the frontend editor.
        """
        return [get_language_object(lang_code) for lang_code in set(self.get_plugins().values_list('language', flat=True))] 

LanguageError at /en/
Language not found: de



Discussion:

Resolving patch:
diff --git a/cms/models/placeholdermodel.py b/cms/models/placeholdermodel.py
--- a/cms/models/placeholdermodel.py
+++ b/cms/models/placeholdermodel.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from cms.exceptions import LanguageError
 from cms.utils import get_cms_setting
 from cms.utils.compat.dj import python_2_unicode_compatible
 from cms.utils.helpers import reversion_register
@@ -223,7 +224,13 @@ def get_filled_languages(self):
 
         This is not cached as it's meant to eb used in the frontend editor.
         """
-        return [get_language_object(lang_code) for lang_code in set(self.get_plugins().values_list('language', flat=True))]
+        languages = []
+        for lang_code in set(self.get_plugins().values_list('language', flat=True)):
+            try:
+                languages.append(get_language_object(lang_code))
+            except LanguageError:
+                pass
+        return languages
 
     def get_cached_plugins(self):
         return getattr(self, '_plugins_cache', [])
diff --git a/cms/plugin_base.py b/cms/plugin_base.py
--- a/cms/plugin_base.py
+++ b/cms/plugin_base.py
@@ -121,7 +121,7 @@ class CMSPluginBase(with_metaclass(CMSPluginBaseMetaclass, admin.ModelAdmin)):
 
     action_options = {
         PLUGIN_MOVE_ACTION: {
-            'requires_reload': True
+            'requires_reload': False
         },
         PLUGIN_COPY_ACTION: {
             'requires_reload': True
diff --git a/cms/views.py b/cms/views.py
--- a/cms/views.py
+++ b/cms/views.py
@@ -21,9 +21,9 @@
 from django.utils.http import urlquote
 from django.utils.timezone import get_current_timezone_name
 
-
 CMS_PAGE_CACHE_VERSION_KEY = 'CMS_PAGE_CACHE_VERSION'
 
+
 def _handle_no_page(request, slug):
     if not slug and settings.DEBUG:
         return TemplateResponse(request, "cms/welcome.html", RequestContext(request))


Test patch:
diff --git a/cms/tests/multilingual.py b/cms/tests/multilingual.py
--- a/cms/tests/multilingual.py
+++ b/cms/tests/multilingual.py
@@ -280,3 +280,17 @@ def test_no_english_defined(self):
             except LanguageError:
                 self.fail("LanguageError raised")
 
+    def test_wrong_plugin_language(self):
+        page = create_page("page", "nav_playground.html", "en", published=True)
+        ph_en = page.placeholders.get(slot="body")
+        text_plugin_1 = add_plugin(ph_en, "TextPlugin", "en", body="I'm the first")
+        title = Title(title="page", slug="page", language="ru", page=page)
+        title.save()
+        # add wrong plugin language
+        text_plugin_2 = add_plugin(ph_en, "TextPlugin", "ru", body="I'm the second")
+        page.publish('en')
+        superuser = self.get_superuser()
+        with self.login_user_context(superuser):
+            response = self.client.get('/en/?edit')
+            self.assertEqual(response.status_code, 200)
+
diff --git a/cms/tests/plugins.py b/cms/tests/plugins.py
--- a/cms/tests/plugins.py
+++ b/cms/tests/plugins.py
@@ -5,15 +5,13 @@
 from cms import api
 
 from cms.api import create_page, publish_page, add_plugin
-from cms.compat import get_user_model
 from cms.constants import PLUGIN_MOVE_ACTION, PLUGIN_COPY_ACTION
 from cms.exceptions import PluginAlreadyRegistered, PluginNotRegistered
 from cms.models import Page, Placeholder
 from cms.models.pluginmodel import CMSPlugin, PluginModelBase
 from cms.plugin_base import CMSPluginBase
 from cms.plugin_pool import plugin_pool
-from cms.test_utils.project.placeholderapp.cms_plugins import EmptyPlugin
-from cms.test_utils.project.pluginapp.plugins.validation.cms_plugins import NonExisitngRenderTemplate, NoSubPluginRender, NoRender, NoRenderButChildren, DynTemplate
+from cms.test_utils.project.pluginapp.plugins.validation.cms_plugins import NonExisitngRenderTemplate, NoRender, NoRenderButChildren, DynTemplate
 from djangocms_googlemap.models import GoogleMap
 from djangocms_inherit.cms_plugins import InheritPagePlaceholderPlugin
 from cms.utils.plugins import get_plugins_for_page
diff --git a/cms/tests/static_placeholder.py b/cms/tests/static_placeholder.py
--- a/cms/tests/static_placeholder.py
+++ b/cms/tests/static_placeholder.py
@@ -2,11 +2,10 @@
 from __future__ import with_statement
 import json
 from cms.api import add_plugin
-from cms.constants import PLUGIN_MOVE_ACTION
+from cms.constants import PLUGIN_MOVE_ACTION, PLUGIN_COPY_ACTION
 from cms.models import StaticPlaceholder, Placeholder, CMSPlugin
 from cms.tests.plugins import PluginsTestBaseCase
 from cms.utils.compat.dj import force_unicode
-from cms.compat import get_user_model
 from django.contrib.admin.sites import site
 from django.template.base import Template
 
@@ -132,7 +131,7 @@ def test_copy_plugin(self):
                     }
                 )
             expected = json.loads(
-                json.dumps({'plugin_list': reduced_list, 'reload': plugin_class.requires_reload(PLUGIN_MOVE_ACTION)}))
+                json.dumps({'plugin_list': reduced_list, 'reload': plugin_class.requires_reload(PLUGIN_COPY_ACTION)}))
             self.assertEqual(response.status_code, 200)
             self.assertEquals(json.loads(response.content.decode('utf8')), expected)