diff options
author | Yoong Kang Lim <yoongkang.lim@gmail.com> | 2016-01-27 22:15:38 +1100 |
---|---|---|
committer | Tim Graham <timograham@gmail.com> | 2016-02-04 19:40:12 -0500 |
commit | 0edb8a146fd6c60f4c3b1ad0a4a89963962f22af (patch) | |
tree | 67940a5d20ae5b4732ba4b263806ea0e230c0973 | |
parent | 04de4369325097472d7ad036dac262555002ba88 (diff) | |
download | django-0edb8a146fd6c60f4c3b1ad0a4a89963962f22af.tar.gz |
Fixed #26144 -- Warned when dumping proxy model without concrete parent.
-rw-r--r-- | django/core/management/commands/dumpdata.py | 14 | ||||
-rw-r--r-- | docs/releases/1.10.txt | 3 | ||||
-rw-r--r-- | tests/fixtures/models.py | 5 | ||||
-rw-r--r-- | tests/fixtures/tests.py | 36 |
4 files changed, 56 insertions, 2 deletions
diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index 1468a92e6c..69c80ff09f 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -1,3 +1,5 @@ +import inspect +import warnings from collections import OrderedDict from django.apps import apps @@ -6,6 +8,10 @@ from django.core.management.base import BaseCommand, CommandError from django.db import DEFAULT_DB_ALIAS, router +class ProxyModelWarning(Warning): + pass + + class Command(BaseCommand): help = ("Output the contents of the database as a fixture of the given " "format (using each model's default manager unless --all is " @@ -132,9 +138,15 @@ class Command(BaseCommand): Collate the objects to be serialized. If count_only is True, just count the number of objects to be serialized. """ - for model in serializers.sort_dependencies(app_list.items()): + models = serializers.sort_dependencies(app_list.items()) + for model in models: if model in excluded_models: continue + if model._meta.proxy and inspect.getmro(model)[1] not in models: + warnings.warn( + "%s is a proxy model and won't be serialized." % model._meta.label, + category=ProxyModelWarning, + ) if not model._meta.proxy and router.allow_migrate_model(using, model): if use_base_manager: objects = model._base_manager diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index 602bf311f3..76729a23be 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -245,6 +245,9 @@ Management Commands * The new :option:`shell --command` option lets you run a command as Django and exit, instead of opening the interactive shell. +* Added a warning to :djadmin:`dumpdata` if a proxy model is specified (which + results in no output) without its concrete parent. + Migrations ~~~~~~~~~~ diff --git a/tests/fixtures/models.py b/tests/fixtures/models.py index 391e030f8c..bfad34c1da 100644 --- a/tests/fixtures/models.py +++ b/tests/fixtures/models.py @@ -92,6 +92,11 @@ class Spy(Person): cover_blown = models.BooleanField(default=False) +class ProxySpy(Spy): + class Meta: + proxy = True + + @python_2_unicode_compatible class Visa(models.Model): person = models.ForeignKey(Person, models.CASCADE) diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py index e7a105532a..4551b11185 100644 --- a/tests/fixtures/tests.py +++ b/tests/fixtures/tests.py @@ -4,12 +4,14 @@ import os import sys import tempfile import unittest +import warnings from django.apps import apps from django.contrib.sites.models import Site from django.core import management from django.core.files.temp import NamedTemporaryFile from django.core.management import CommandError +from django.core.management.commands.dumpdata import ProxyModelWarning from django.core.serializers.base import ProgressBar from django.db import IntegrityError, connection from django.test import ( @@ -18,7 +20,7 @@ from django.test import ( from django.utils import six from django.utils.encoding import force_text -from .models import Article, Spy, Tag, Visa +from .models import Article, ProxySpy, Spy, Tag, Visa class TestCaseFixtureLoadingTests(TestCase): @@ -476,6 +478,38 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): management.call_command('dumpdata', 'fixtures', **options) self.assertEqual(new_io.getvalue(), '') + def test_dumpdata_proxy_without_concrete(self): + """ + A warning is displayed if a proxy model is dumped without its concrete + parent. + """ + ProxySpy.objects.create(name='Paul') + + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter('always') + self._dumpdata_assert(['fixtures.ProxySpy'], '[]') + warning = warning_list.pop() + self.assertEqual(warning.category, ProxyModelWarning) + self.assertEqual( + str(warning.message), + "fixtures.ProxySpy is a proxy model and won't be serialized." + ) + + def test_dumpdata_proxy_with_concrete(self): + """ + A warning isn't displayed if a proxy model is dumped with its concrete + parent. + """ + spy = ProxySpy.objects.create(name='Paul') + + with warnings.catch_warnings(record=True) as warning_list: + warnings.simplefilter('always') + self._dumpdata_assert( + ['fixtures.ProxySpy', 'fixtures.Spy'], + '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % spy.pk + ) + self.assertEqual(len(warning_list), 0) + def test_compress_format_loading(self): # Load fixture 4 (compressed), using format specification management.call_command('loaddata', 'fixture4.json', verbosity=0) |