summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Graham <timograham@gmail.com>2016-07-15 11:07:43 -0400
committerTim Graham <timograham@gmail.com>2016-08-10 21:19:09 -0400
commite2dfa81ff7489d97700604d634adacf1384af184 (patch)
tree820b7dbbcf611b5f18e02375cc3e2d9dbea5ab98
parent7399fee6c3bb7eded1ecf5855d71520db299d79d (diff)
Refs #18682 -- Edited explanation in stale content type deletion.
Follow up to 8db889eaf7dce0cb715b075be32047c1b1b316da.
-rw-r--r--django/contrib/contenttypes/management.py19
-rw-r--r--docs/releases/1.11.txt7
-rw-r--r--tests/contenttypes_tests/models.py1
-rw-r--r--tests/contenttypes_tests/tests.py16
4 files changed, 23 insertions, 20 deletions
diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py
index 591f96705b..aa1c198fc4 100644
--- a/django/contrib/contenttypes/management.py
+++ b/django/contrib/contenttypes/management.py
@@ -154,22 +154,20 @@ def update_contenttypes(app_config, verbosity=2, interactive=True, using=DEFAULT
for obj_type, objs in collector.data.items():
if objs == {ct}:
continue
- ct_info.append(' - %s object%s of type %s.%s:' % (
+ ct_info.append(' - %s %s object(s)' % (
len(objs),
- 's' if len(objs) != 1 else '',
- obj_type._meta.app_label,
- obj_type._meta.model_name)
- )
+ obj_type._meta.label,
+ ))
content_type_display = '\n'.join(ct_info)
print("""Some content types in your database are stale and can be deleted.
-Any objects that depend on these content types will then also be deleted.
-The content types, and the dependent objects that would be deleted, are:
+Any objects that depend on these content types will also be deleted.
+The content types and dependent objects that would be deleted are:
%s
-This list does not include data that might be in your database
-outside of Django's models.
+This list doesn't include any cascade deletions to data outside of Django's
+models (uncommon).
Are you sure you want to delete these content types?
If you're unsure, answer 'no'.
@@ -191,7 +189,6 @@ If you're unsure, answer 'no'.
class NoFastDeleteCollector(Collector):
def can_fast_delete(self, *args, **kwargs):
"""
- We always want to load the objects into memory so that we can display
- them to the user when asking confirmation.
+ Always load related objects to display them when showing confirmation.
"""
return False
diff --git a/docs/releases/1.11.txt b/docs/releases/1.11.txt
index 64a5fc2780..9d2ccb0f6b 100644
--- a/docs/releases/1.11.txt
+++ b/docs/releases/1.11.txt
@@ -87,10 +87,9 @@ Minor features
:mod:`django.contrib.contenttypes`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* When stale content types are detected during a management command, there is
- now an expansive list of objects that will be deleted. Previously, only
- the content type objects themselves were listed, even if there were objects
- with foreign keys towards the content types that would be deleted also.
+* When stale content types are detected after the ``migrate`` command, there's
+ now a list of related objects such as ``auth.Permission``\s that will also be
+ deleted. Previously, only the content types were listed.
:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/contenttypes_tests/models.py b/tests/contenttypes_tests/models.py
index 4b9d3d31e6..fe1854e8a3 100644
--- a/tests/contenttypes_tests/models.py
+++ b/tests/contenttypes_tests/models.py
@@ -131,6 +131,7 @@ class Post(models.Model):
class ModelWithNullFKToSite(models.Model):
title = models.CharField(max_length=200)
site = models.ForeignKey(Site, null=True, on_delete=models.CASCADE)
+ post = models.ForeignKey(Post, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
diff --git a/tests/contenttypes_tests/tests.py b/tests/contenttypes_tests/tests.py
index 5c8c675a4a..6d57a23355 100644
--- a/tests/contenttypes_tests/tests.py
+++ b/tests/contenttypes_tests/tests.py
@@ -389,21 +389,27 @@ class UpdateContentTypesTests(TestCase):
def test_interactive_true_with_dependent_objects(self):
"""
interactive mode of update_contenttypes() (the default) should delete
- stale contenttypes and warn of dependent objects
+ stale contenttypes and warn of dependent objects.
"""
- Post.objects.create(title='post', content_type=self.content_type)
+ post = Post.objects.create(title='post', content_type=self.content_type)
+ # A related object is needed to show that a custom collector with
+ # can_fast_delete=False is needed.
+ ModelWithNullFKToSite.objects.create(post=post)
contenttypes_management.input = lambda x: force_str("yes")
with captured_stdout() as stdout:
contenttypes_management.update_contenttypes(self.app_config)
self.assertEqual(Post.objects.count(), 0)
- self.assertIn("1 object of type contenttypes_tests.post:", stdout.getvalue())
- self.assertIn("Deleting stale content type", stdout.getvalue())
+ output = stdout.getvalue()
+ self.assertIn('- Content type for contenttypes_tests.Fake', output)
+ self.assertIn('- 1 contenttypes_tests.Post object(s)', output)
+ self.assertIn('- 1 contenttypes_tests.ModelWithNullFKToSite', output)
+ self.assertIn('Deleting stale content type', output)
self.assertEqual(ContentType.objects.count(), self.before_count)
def test_interactive_true_without_dependent_objects(self):
"""
interactive mode of update_contenttypes() (the default) should delete
- stale contenttypes and inform there are no dependent objects
+ stale contenttypes even if there aren't any dependent objects.
"""
contenttypes_management.input = lambda x: force_str("yes")
with captured_stdout() as stdout: