Commit 0edb8a14 authored by Yoong Kang Lim's avatar Yoong Kang Lim Committed by Tim Graham
Browse files

Fixed #26144 -- Warned when dumping proxy model without concrete parent.

parent 04de4369
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
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
+3 −0
Original line number Diff line number Diff line
@@ -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
~~~~~~~~~~

+5 −0
Original line number Diff line number Diff line
@@ -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)
+35 −1
Original line number Diff line number Diff line
@@ -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)