mirror of https://github.com/django/django.git
Fixed #26144 -- Warned when dumping proxy model without concrete parent.
This commit is contained in:
parent
04de436932
commit
0edb8a146f
|
@ -1,3 +1,5 @@
|
||||||
|
import inspect
|
||||||
|
import warnings
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from django.apps import apps
|
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
|
from django.db import DEFAULT_DB_ALIAS, router
|
||||||
|
|
||||||
|
|
||||||
|
class ProxyModelWarning(Warning):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = ("Output the contents of the database as a fixture of the given "
|
help = ("Output the contents of the database as a fixture of the given "
|
||||||
"format (using each model's default manager unless --all is "
|
"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
|
Collate the objects to be serialized. If count_only is True, just
|
||||||
count the number of objects to be serialized.
|
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:
|
if model in excluded_models:
|
||||||
continue
|
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 not model._meta.proxy and router.allow_migrate_model(using, model):
|
||||||
if use_base_manager:
|
if use_base_manager:
|
||||||
objects = model._base_manager
|
objects = model._base_manager
|
||||||
|
|
|
@ -245,6 +245,9 @@ Management Commands
|
||||||
* The new :option:`shell --command` option lets you run a command as Django and
|
* The new :option:`shell --command` option lets you run a command as Django and
|
||||||
exit, instead of opening the interactive shell.
|
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
|
Migrations
|
||||||
~~~~~~~~~~
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,11 @@ class Spy(Person):
|
||||||
cover_blown = models.BooleanField(default=False)
|
cover_blown = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
|
||||||
|
class ProxySpy(Spy):
|
||||||
|
class Meta:
|
||||||
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Visa(models.Model):
|
class Visa(models.Model):
|
||||||
person = models.ForeignKey(Person, models.CASCADE)
|
person = models.ForeignKey(Person, models.CASCADE)
|
||||||
|
|
|
@ -4,12 +4,14 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.core import management
|
from django.core import management
|
||||||
from django.core.files.temp import NamedTemporaryFile
|
from django.core.files.temp import NamedTemporaryFile
|
||||||
from django.core.management import CommandError
|
from django.core.management import CommandError
|
||||||
|
from django.core.management.commands.dumpdata import ProxyModelWarning
|
||||||
from django.core.serializers.base import ProgressBar
|
from django.core.serializers.base import ProgressBar
|
||||||
from django.db import IntegrityError, connection
|
from django.db import IntegrityError, connection
|
||||||
from django.test import (
|
from django.test import (
|
||||||
|
@ -18,7 +20,7 @@ from django.test import (
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.encoding import force_text
|
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):
|
class TestCaseFixtureLoadingTests(TestCase):
|
||||||
|
@ -476,6 +478,38 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase):
|
||||||
management.call_command('dumpdata', 'fixtures', **options)
|
management.call_command('dumpdata', 'fixtures', **options)
|
||||||
self.assertEqual(new_io.getvalue(), '')
|
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):
|
def test_compress_format_loading(self):
|
||||||
# Load fixture 4 (compressed), using format specification
|
# Load fixture 4 (compressed), using format specification
|
||||||
management.call_command('loaddata', 'fixture4.json', verbosity=0)
|
management.call_command('loaddata', 'fixture4.json', verbosity=0)
|
||||||
|
|
Loading…
Reference in New Issue