Refs #18682 -- Edited explanation in stale content type deletion.

Follow up to 8db889eaf7.
This commit is contained in:
Tim Graham 2016-07-15 11:07:43 -04:00
parent 7399fee6c3
commit e2dfa81ff7
4 changed files with 23 additions and 20 deletions

View File

@ -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

View File

@ -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`
~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -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

View File

@ -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: