django-cms: IntegrityError: Duplicate entry for key 'publisher_public_id'

I am unable to publish a page. Not sure what’s causing this issue.

Here’s the stack trace:

Environment:


Request Method: GET
Request URL: en/admin/cms/page/11/en/publish/

Django Version: 1.6.5
Python Version: 2.7.7
Installed Applications:
('djangocms_admin_style',
 'djangocms_text_ckeditor',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.admin',
 'django.contrib.sites',
 'django.contrib.sitemaps',
 'django.contrib.staticfiles',
 'django.contrib.messages',
 'filer',
 'easy_thumbnails',
 'cmsplugin_cascade',
 'cmsplugin_filer_file',
 'cmsplugin_filer_folder',
 'cmsplugin_filer_image',
 'cmsplugin_filer_teaser',
 'cmsplugin_filer_video',
 'cms',
 'mptt',
 'menus',
 'south',
 'sekizai',
 'djangocms_style',
 'djangocms_column',
 'djangocms_file',
 'djangocms_flash',
 'djangocms_googlemap',
 'djangocms_inherit',
 'djangocms_link',
 'djangocms_picture',
 'djangocms_teaser',
 'djangocms_video',
 'reversion',
 'foo',
 'django_extensions')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.doc.XViewMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'cms.middleware.user.CurrentUserMiddleware',
 'cms.middleware.page.CurrentPageMiddleware',
 'cms.middleware.toolbar.ToolbarMiddleware',
 'cms.middleware.language.LanguageCookieMiddleware')


Traceback:
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  112.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
  99.                     response = view_func(request, *args, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  52.         response = view_func(request, *args, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
  198.             return view(request, *args, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/transaction.py" in inner
  431.                 return func(*args, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/reversion/revisions.py" in do_revision_context
  300.                     return func(*args, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/cms/admin/pageadmin.py" in publish_page
  1049.             published = page.publish(language)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/cms/models/pagemodel.py" in publish
  572.                 public_page.save()
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/cms/models/pagemodel.py" in save
  455.                 super(Page, self).save(**kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/mptt/models.py" in save
  717.         super(MPTTModel, self).save(*args, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/models/base.py" in save
  545.                        force_update=force_update, update_fields=update_fields)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/cms/models/pagemodel.py" in save_base
  473.         ret = super(Page, self).save_base(*args, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/models/base.py" in save_base
  573.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/models/base.py" in _save_table
  654.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/models/base.py" in _do_insert
  687.                                using=using, raw=raw)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/models/manager.py" in _insert
  232.         return insert_query(self.model, objs, fields, **kwargs)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/models/query.py" in insert_query
  1514.     return query.get_compiler(using=using).execute_sql(return_id)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
  903.             cursor.execute(sql, params)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/backends/util.py" in execute
  69.             return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/backends/util.py" in execute
  53.                 return self.cursor.execute(sql, params)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/utils.py" in __exit__
  99.                 six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/backends/util.py" in execute
  53.                 return self.cursor.execute(sql, params)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/django/db/backends/mysql/base.py" in execute
  124.             return self.cursor.execute(query, args)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/MySQLdb/cursors.py" in execute
  205.             self.errorhandler(self, exc, value)
File "/home/foo/.virtualenvs/foo/lib/python2.7/site-packages/MySQLdb/connections.py" in defaulterrorhandler
  36.     raise errorclass, errorvalue

Exception Type: IntegrityError at /en/admin/cms/page/11/en/publish/
Exception Value: (1062, "Duplicate entry '11' for key 'publisher_public_id'")

Any help would be appreciated. Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Comments: 16 (4 by maintainers)

Most upvoted comments

Hello.

We’ve experienced this sporadically in recent weeks in Django 1.7, Django-CMS 3.1. Unfortunately, it can basically bring a site down due to unhandled exceptions in cms.api.get_page_draft.

I’ve written a Django management command (tested on Python 2.7, Django 1.8.8, Django-CMS 3.2.0) to fix broken cms_page.publisher_public_id columns:

from django.core.management.base import BaseCommand

from cms.api import get_page_draft
from cms.models import Page


class Command(BaseCommand):
    help = 'Fix CMS pages (publisher_public_id foreign key)'

    def __init__(self, *args, **kwargs):
        self._fixed_count = 0
        super(Command, self).__init__(*args, **kwargs)

    def handle(self, *args, **options):
        self._fixed_count = 0
        self.stdout.write('Checking all non-draft pages ...')
        ps = Page.objects.filter(publisher_is_draft=False)
        for p in ps:
            try:
                get_page_draft(p)
            except Page.DoesNotExist:
                self._fix_cms_page(p)
        self.stdout.write('Fixed {} page(s).'.format(self._fixed_count))

    def _fix_cms_page(self, p):
        self.stdout.write('Fixing non-draft page id {} with no publisher_public_id ...'.format(p.id))
        draft_page_id = None

        if Page.objects.filter(id=p.publisher_public_id, publisher_is_draft=True).exists():
            draft_page_id = p.publisher_public_id
        elif Page.objects.filter(id=p.id - 1, publisher_is_draft=True).exists():
            draft_page_id = p.id - 1

        if draft_page_id is None:
            self.stdout.write('Cannot find a draft page corresponding to non-draft page id {}.'.format(p.id))
        else:
            # fix draft page
            draft_page = Page.objects.get(id=draft_page_id, publisher_is_draft=True)
            draft_page.publisher_public_id = p.id
            draft_page.save()

            # fix non-draft page (if necessary)
            if p.publisher_public_id is None:
                p.publisher_public_id = draft_page.id
                p.save()

            # success
            self._fixed_count += 1

Note that when it’s looking for the draft equivalent of a non-draft page, if it can’t find it from the publisher_public_id foreign key, it assumes the draft page id will be one less than the non-draft page id. This may not necessarily be the case if successive draft pages were created without non-draft equivalents, and therefore could mess up the cms_page table. Use with caution.

I’ve really only posted this here to demonstrate that this issue (at least in Django 1.7, Django-CMS 3.1) hasn’t gone away, and is serious enough for us to have had to come up with this management command.

Unfortunately, the issue is intermittent and I cannot reproduce the problem (otherwise, I’d run it through a debugger and try to provide better information).