mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-20 04:51:55 +00:00
Prevent cascade deletion of pages when a ContentType is deleted
Fixes #2024
This commit is contained in:
parent
d8bceff38b
commit
078491b6e0
5 changed files with 57 additions and 3 deletions
|
|
@ -7,6 +7,7 @@ Changelog
|
|||
* The `Document` model can now be overridden using the new `WAGTAILDOCS_DOCUMENT_MODEL` setting (Alex Gleason)
|
||||
* Fix: Custom page managers no longer raise an error when used on an abstract model
|
||||
* Fix: Wagtail's migrations are now all reversible (benjaoming)
|
||||
* Fix: Deleting a page content type now preserves existing pages as basic Page instances, to prevent tree corruption
|
||||
|
||||
1.3.1 (05.01.2016)
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ Bug fixes
|
|||
|
||||
* Custom page managers no longer raise an error when used on an abstract model
|
||||
* Wagtail's migrations are now all reversible (benjaoming)
|
||||
* Deleting a page content type now preserves existing pages as basic Page instances, to prevent tree corruption
|
||||
|
||||
|
||||
Upgrade considerations
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9 on 2015-12-22 09:34
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import wagtail.wagtailcore.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wagtailcore', '0023_alter_page_revision_on_delete_behaviour'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='page',
|
||||
name='content_type',
|
||||
field=models.ForeignKey(on_delete=models.SET(wagtail.wagtailcore.models.get_default_page_content_type), related_name='pages', to='contenttypes.ContentType', verbose_name='content type'),
|
||||
),
|
||||
]
|
||||
|
|
@ -205,6 +205,14 @@ def get_page_models():
|
|||
return PAGE_MODEL_CLASSES
|
||||
|
||||
|
||||
def get_default_page_content_type():
|
||||
"""
|
||||
Returns the content type to use as a default for pages whose content type
|
||||
has been deleted.
|
||||
"""
|
||||
return ContentType.objects.get_for_model(Page)
|
||||
|
||||
|
||||
def get_page_types():
|
||||
"""
|
||||
DEPRECATED.
|
||||
|
|
@ -277,7 +285,12 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed
|
|||
)
|
||||
# TODO: enforce uniqueness on slug field per parent (will have to be done at the Django
|
||||
# level rather than db, since there is no explicit parent relation in the db)
|
||||
content_type = models.ForeignKey('contenttypes.ContentType', verbose_name=_('content type'), related_name='pages')
|
||||
content_type = models.ForeignKey(
|
||||
'contenttypes.ContentType',
|
||||
verbose_name=_('content type'),
|
||||
related_name='pages',
|
||||
on_delete=models.SET(get_default_page_content_type)
|
||||
)
|
||||
live = models.BooleanField(verbose_name=_('live'), default=True, editable=False)
|
||||
has_unpublished_changes = models.BooleanField(
|
||||
verbose_name=_('has unpublished changes'),
|
||||
|
|
@ -452,8 +465,6 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed
|
|||
for model in [cls] + list(cls._meta.get_parent_list())
|
||||
for field in model._meta.parents.values() if field]
|
||||
|
||||
field_exceptions += ['content_type']
|
||||
|
||||
for field in cls._meta.fields:
|
||||
if isinstance(field, models.ForeignKey) and field.name not in field_exceptions:
|
||||
if field.rel.on_delete == models.CASCADE:
|
||||
|
|
|
|||
|
|
@ -1036,3 +1036,23 @@ class TestPageManager(TestCase):
|
|||
their custom Manager inherits from PageManager.
|
||||
"""
|
||||
self.assertIs(type(MyCustomPage.objects), CustomManager)
|
||||
|
||||
|
||||
class TestIssue2024(TestCase):
|
||||
"""
|
||||
This tests that deleting a content type can't delete any Page objects.
|
||||
"""
|
||||
fixtures = ['test.json']
|
||||
|
||||
def test_delete_content_type(self):
|
||||
event_index = Page.objects.get(url_path='/home/events/')
|
||||
|
||||
# Delete the content type
|
||||
event_index_content_type = event_index.content_type
|
||||
event_index_content_type.delete()
|
||||
|
||||
# Fetch the page again, it should still exist
|
||||
event_index = Page.objects.get(url_path='/home/events/')
|
||||
|
||||
# Check that the content_type changed to Page
|
||||
self.assertEqual(event_index.content_type, ContentType.objects.get_for_model(Page))
|
||||
|
|
|
|||
Loading…
Reference in a new issue