Repository: django-cms/django-cms

Issue:
Reverse for 'pages-details-by-slug' exception when publishing a page
This happened when publishing a modified page (that previously had some orphaned plugins, I don't know if that matters)

/home/djangocms/.virtualenv/src/django-cms-origin/cms/models/pagemodel.py in get_absolute_url LINE 132

```
    def is_dirty(self):
        return self.publisher_state == self.PUBLISHER_STATE_DIRTY
    def get_absolute_url(self, language=None, fallback=True):
        if self.is_home():
            return reverse('pages-root')
        path = self.get_path(language, fallback) or self.get_slug(language, fallback)
        return reverse('pages-details-by-slug', kwargs={"slug": path}) ...
    def move_page(self, target, position='first-child'):
        """
        Called from admin interface when page is moved. Should be used on
        all the places which are changing page position. Used like an interface
        to mptt, but after move is done page_moved signal is fired.
```

```
Variable    Value
path    ''
fallback    True
self    <cms.models.pagemodel.Page object at 0x4511cd0>
language    None
```

the `path` is empty, and I don't know why... can I help more?



Discussion:
what version of the cms?

latest from `develop` branch

mmh there seams to be a problem with the migrations.... can you move around the "home" page so a new one gets set as home and try again?

Hello! I think I found the issue. it comes from the fact that the website language and admin language are not necessarily the same.

In the specific of the current development, the website is a multilanguage site with French as the main language; so I click on "French" in the language selector on the website, and do everything from there in French.

BUT! The admin is still following my browser language config, and comes in English.

Basically if I do:

http://www.mysite.com/ => redirects to http://www.mysite.com/fr/home

but if I click on any admin link or even simply do 

http://www.mysite.com/admin => redirects to http://www.mysite.com/en/admin

And of course this means the whole toolbar is in English, while the site is in French.

Now, if - as often - I created the page in French only, it will have no slug (nor name) in English yet!

Thus when I click on "publish", the redirects make it use the "EN" slug, which is missing, and hits the error.

I don't know what the generic best strategy for this situation would be, as it might not be desired to have the admin switch language with the website. Maybe at least the "publish changes" button should work with a specific case?

I don't really see in

`django-cms/cms/admin/pageadmin.py in publish_page`

```
980: path = '%s?edit_off' % public_page.get_absolute_url() 
```

how to get the 'site' language rather then the admin one...


Resolving patch:
diff --git a/cms/admin/pageadmin.py b/cms/admin/pageadmin.py
--- a/cms/admin/pageadmin.py
+++ b/cms/admin/pageadmin.py
@@ -944,7 +944,7 @@ def publish_page(self, request, page_id, language):
                 user_id=request.user.id,
                 content_type_id=ContentType.objects.get_for_model(Page).pk,
                 object_id=page_id,
-                object_repr=page.get_title(),
+                object_repr=page.get_title(language),
                 action_flag=CHANGE,
             )
         else:
@@ -983,7 +983,7 @@ def publish_page(self, request, page_id, language):
             if all_published:
                 if page:
                     public_page = Page.objects.get(publisher_public=page.pk)
-                    path = '%s?edit_off' % public_page.get_absolute_url()
+                    path = '%s?edit_off' % public_page.get_absolute_url(language, fallback=True)
                 else:
                     path = '%s?edit_off' % referrer
             else:
diff --git a/cms/models/pagemodel.py b/cms/models/pagemodel.py
--- a/cms/models/pagemodel.py
+++ b/cms/models/pagemodel.py
@@ -6,7 +6,7 @@
 from os.path import join
 from cms import constants
 from cms.constants import PUBLISHER_STATE_DEFAULT, PUBLISHER_STATE_PENDING, PUBLISHER_STATE_DIRTY, TEMPLATE_INHERITANCE_MAGIC
-from cms.exceptions import PublicIsUnmodifiable
+from cms.exceptions import PublicIsUnmodifiable, LanguageError
 from cms.models.managers import PageManager, PagePermissionsPermissionManager
 from cms.models.metaclasses import PageMetaClass
 from cms.models.placeholdermodel import Placeholder
@@ -108,7 +108,13 @@ class PublisherMeta:
             'parent']
 
     def __str__(self):
-        title = self.get_menu_title(fallback=True)
+        try:
+            title = self.get_menu_title(fallback=True)
+        except LanguageError:
+            try:
+                title = self.title_set.all()[0]
+            except IndexError:
+                title = None
         if title is None:
             title = u""
         return force_unicode(title)


Test patch:
diff --git a/cms/tests/publisher.py b/cms/tests/publisher.py
--- a/cms/tests/publisher.py
+++ b/cms/tests/publisher.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import with_statement
 from cms.constants import PUBLISHER_STATE_PENDING, PUBLISHER_STATE_DEFAULT, PUBLISHER_STATE_DIRTY
+from cms.utils.i18n import force_language
 from django.contrib.auth.models import User
 from django.core.management.base import CommandError
 from django.core.urlresolvers import reverse
@@ -11,7 +12,7 @@
 from cms.models.pagemodel import Page
 from cms.plugin_pool import plugin_pool
 from cms.test_utils.testcases import SettingsOverrideTestCase as TestCase
-from cms.test_utils.util.context_managers import StdoutOverride
+from cms.test_utils.util.context_managers import StdoutOverride, SettingsOverride
 
 from djangocms_text_ckeditor.models import Text
 
@@ -102,7 +103,7 @@ def test_table_name_patching(self):
             com = publisher_publish.Command()
             com.handle_noargs()
             lines = buffer.getvalue().split('\n') #NB: readlines() doesn't work
-        # Sanity check the database (we should have one draft and one public)
+            # Sanity check the database (we should have one draft and one public)
         not_drafts = len(Page.objects.filter(publisher_is_draft=False))
         drafts = len(Page.objects.filter(publisher_is_draft=True))
         self.assertEquals(not_drafts, 1)
@@ -158,6 +159,7 @@ def tearDown(self):
         plugin_pool.patched = False
         plugin_pool.set_plugin_meta()
 
+
 class PublishingTests(TestCase):
     def create_page(self, title=None, **kwargs):
         return create_page(title or self._testMethodName,
@@ -215,6 +217,19 @@ def test_publish_admin(self):
 
         self.assertEqual(page.get_publisher_state('en'), 0)
 
+    def test_publish_wrong_lang(self):
+        page = self.create_page("test_admin", published=False)
+        superuser = self.get_superuser()
+        with SettingsOverride(
+                LANGUAGES=(('de', 'de'), ('en', 'en')),
+                CMS_LANGUAGES={1: [{'code': 'en', 'name': 'en', 'fallbacks': ['fr', 'de'], 'public': True}]}
+            ):
+            with self.login_user_context(superuser):
+                with force_language('de'):
+                    response = self.client.get(reverse("admin:cms_page_publish_page", args=[page.pk, 'en']))
+        self.assertEqual(response.status_code, 302)
+        page = Page.objects.get(pk=page.pk)
+
     def test_publish_child_first(self):
         parent = self.create_page('parent', published=False)
         child = self.create_page('child', published=False, parent=parent)
@@ -360,8 +375,6 @@ def test_publish_ordering2(self):
             x += 1
 
 
-
-
     def test_unpublish_unpublish(self):
         name = self._testMethodName
         page = self.create_page(name, published=True)
@@ -616,10 +629,10 @@ def test_republish_multiple_root(self):
         self.assertEqual(home.get_absolute_url(), root + 'page/')
         self.assertEqual(home.get_public_object().get_absolute_url(), root + 'page/')
 
-        self.assertEqual(child.get_absolute_url(), root+'page/child/')
-        self.assertEqual(child.get_public_object().get_absolute_url(), root+'page/child/')
-        self.assertEqual(child2.get_absolute_url(), root+'child/')
-        self.assertEqual(child2.get_public_object().get_absolute_url(), root+'child/')
+        self.assertEqual(child.get_absolute_url(), root + 'page/child/')
+        self.assertEqual(child.get_public_object().get_absolute_url(), root + 'page/child/')
+        self.assertEqual(child2.get_absolute_url(), root + 'child/')
+        self.assertEqual(child2.get_public_object().get_absolute_url(), root + 'child/')
         home.publish('en')
         home = self.reload(home)
         other = self.reload(other)