summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoong Kang Lim <yoongkang.lim@gmail.com>2016-01-27 22:15:38 +1100
committerTim Graham <timograham@gmail.com>2016-02-04 19:40:12 -0500
commit0edb8a146fd6c60f4c3b1ad0a4a89963962f22af (patch)
tree67940a5d20ae5b4732ba4b263806ea0e230c0973
parent04de4369325097472d7ad036dac262555002ba88 (diff)
downloaddjango-0edb8a146fd6c60f4c3b1ad0a4a89963962f22af.tar.gz
Fixed #26144 -- Warned when dumping proxy model without concrete parent.
-rw-r--r--django/core/management/commands/dumpdata.py14
-rw-r--r--docs/releases/1.10.txt3
-rw-r--r--tests/fixtures/models.py5
-rw-r--r--tests/fixtures/tests.py36
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)