diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index d2fe6cdd07..706bf601f9 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -19,9 +19,12 @@ class Command(BaseCommand): help='An appname or appname.ModelName to exclude (use multiple --exclude to exclude multiple apps/models).'), make_option('-n', '--natural', action='store_true', dest='use_natural_keys', default=False, help='Use natural keys if they are available.'), + make_option('-a', '--all', action='store_true', dest='use_base_manager', default=False, + help="Use Django's base manager to dump all models stored in the database, including those that would otherwise be filtered or modified by a custom manager."), ) help = ("Output the contents of the database as a fixture of the given " - "format (using each model's default manager).") + "format (using each model's default manager unless --all is " + "specified).") args = '[appname appname.ModelName ...]' def handle(self, *app_labels, **options): @@ -34,6 +37,7 @@ class Command(BaseCommand): excludes = options.get('exclude',[]) show_traceback = options.get('traceback', False) use_natural_keys = options.get('use_natural_keys', False) + use_base_manager = options.get('use_base_manager', False) excluded_apps = set() excluded_models = set() @@ -100,7 +104,10 @@ class Command(BaseCommand): if model in excluded_models: continue if not model._meta.proxy and router.allow_syncdb(using, model): - objects.extend(model._default_manager.using(using).all()) + if use_base_manager: + objects.extend(model._base_manager.using(using).all()) + else: + objects.extend(model._default_manager.using(using).all()) try: return serializers.serialize(format, objects, indent=indent, diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt index 67b1b6c9db..6d0993c7f0 100644 --- a/docs/ref/django-admin.txt +++ b/docs/ref/django-admin.txt @@ -208,6 +208,12 @@ records to dump. If you're using a :ref:`custom manager ` as the default manager and it filters some of the available records, not all of the objects will be dumped. +.. versionadded:: 1.3 + +The :djadminopt:`--all` option may be provided to specify that +``dumpdata`` should use Django's base manager, dumping records which +might otherwise be filtered or modified by a custom manager. + .. django-admin-option:: --format By default, ``dumpdata`` will format its output in JSON, but you can use the @@ -271,7 +277,6 @@ prompts. The :djadminopt:`--database` option may be used to specify the database to flush. - inspectdb --------- diff --git a/tests/modeltests/fixtures/models.py b/tests/modeltests/fixtures/models.py index 216a8e2502..0035bcc7e0 100644 --- a/tests/modeltests/fixtures/models.py +++ b/tests/modeltests/fixtures/models.py @@ -72,6 +72,14 @@ class Person(models.Model): def natural_key(self): return (self.name,) +class SpyManager(PersonManager): + def get_query_set(self): + return super(SpyManager, self).get_query_set().filter(cover_blown=False) + +class Spy(Person): + objects = SpyManager() + cover_blown = models.BooleanField(default=False) + class Visa(models.Model): person = models.ForeignKey(Person) permissions = models.ManyToManyField(Permission, blank=True) diff --git a/tests/modeltests/fixtures/tests.py b/tests/modeltests/fixtures/tests.py index e818423b48..799a7328da 100644 --- a/tests/modeltests/fixtures/tests.py +++ b/tests/modeltests/fixtures/tests.py @@ -6,7 +6,7 @@ from django.conf import settings from django.core import management from django.db import DEFAULT_DB_ALIAS -from models import Article, Blog, Book, Category, Person, Tag, Visa +from models import Article, Blog, Book, Category, Person, Spy, Tag, Visa class TestCaseFixtureLoadingTests(TestCase): fixtures = ['fixture1.json', 'fixture2.json'] @@ -24,12 +24,13 @@ class TestCaseFixtureLoadingTests(TestCase): class FixtureLoadingTests(TestCase): def _dumpdata_assert(self, args, output, format='json', natural_keys=False, - exclude_list=[]): + use_base_manager=False, exclude_list=[]): new_io = StringIO.StringIO() management.call_command('dumpdata', *args, **{'format':format, 'stdout':new_io, 'stderr':new_io, 'use_natural_keys':natural_keys, + 'use_base_manager':use_base_manager, 'exclude': exclude_list}) command_output = new_io.getvalue().strip() self.assertEqual(command_output, output) @@ -197,6 +198,17 @@ class FixtureLoadingTests(TestCase): '', exclude_list=['fixtures.FooModel']) + def test_dumpdata_with_filtering_manager(self): + Spy(name='Paul').save() + Spy(name='Alex', cover_blown=True).save() + self.assertQuerysetEqual(Spy.objects.all(), + ['']) + # Use the default manager + self._dumpdata_assert(['fixtures.Spy'],'[{"pk": 1, "model": "fixtures.spy", "fields": {"cover_blown": false}}]') + # Dump using Django's base manager. Should return all objects, + # even those normally filtered by the manager + self._dumpdata_assert(['fixtures.Spy'], '[{"pk": 2, "model": "fixtures.spy", "fields": {"cover_blown": true}}, {"pk": 1, "model": "fixtures.spy", "fields": {"cover_blown": false}}]', use_base_manager=True) + def test_compress_format_loading(self): # Load fixture 4 (compressed), using format specification management.call_command('loaddata', 'fixture4.json', verbosity=0, commit=False)