Fixed #14162 - Dumpdata needs an option to use the base manager instead of the default manager

Thanks to PaulM for suggestion and patch.



git-svn-id: http://code.djangoproject.com/svn/django/trunk@13669 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2010-08-30 11:58:26 +00:00
parent f9d051d5f0
commit 5deb3e5a62
4 changed files with 37 additions and 5 deletions

View File

@ -19,9 +19,12 @@ class Command(BaseCommand):
help='An appname or appname.ModelName to exclude (use multiple --exclude to exclude multiple apps/models).'), 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, make_option('-n', '--natural', action='store_true', dest='use_natural_keys', default=False,
help='Use natural keys if they are available.'), 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 " 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 ...]' args = '[appname appname.ModelName ...]'
def handle(self, *app_labels, **options): def handle(self, *app_labels, **options):
@ -34,6 +37,7 @@ class Command(BaseCommand):
excludes = options.get('exclude',[]) excludes = options.get('exclude',[])
show_traceback = options.get('traceback', False) show_traceback = options.get('traceback', False)
use_natural_keys = options.get('use_natural_keys', False) use_natural_keys = options.get('use_natural_keys', False)
use_base_manager = options.get('use_base_manager', False)
excluded_apps = set() excluded_apps = set()
excluded_models = set() excluded_models = set()
@ -100,7 +104,10 @@ class Command(BaseCommand):
if model in excluded_models: if model in excluded_models:
continue continue
if not model._meta.proxy and router.allow_syncdb(using, model): 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: try:
return serializers.serialize(format, objects, indent=indent, return serializers.serialize(format, objects, indent=indent,

View File

@ -208,6 +208,12 @@ records to dump. If you're using a :ref:`custom manager <custom-managers>` as
the default manager and it filters some of the available records, not all of the the default manager and it filters some of the available records, not all of the
objects will be dumped. 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 <fmt> .. django-admin-option:: --format <fmt>
By default, ``dumpdata`` will format its output in JSON, but you can use the 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 The :djadminopt:`--database` option may be used to specify the database
to flush. to flush.
inspectdb inspectdb
--------- ---------

View File

@ -72,6 +72,14 @@ class Person(models.Model):
def natural_key(self): def natural_key(self):
return (self.name,) 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): class Visa(models.Model):
person = models.ForeignKey(Person) person = models.ForeignKey(Person)
permissions = models.ManyToManyField(Permission, blank=True) permissions = models.ManyToManyField(Permission, blank=True)

View File

@ -6,7 +6,7 @@ from django.conf import settings
from django.core import management from django.core import management
from django.db import DEFAULT_DB_ALIAS 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): class TestCaseFixtureLoadingTests(TestCase):
fixtures = ['fixture1.json', 'fixture2.json'] fixtures = ['fixture1.json', 'fixture2.json']
@ -24,12 +24,13 @@ class TestCaseFixtureLoadingTests(TestCase):
class FixtureLoadingTests(TestCase): class FixtureLoadingTests(TestCase):
def _dumpdata_assert(self, args, output, format='json', natural_keys=False, def _dumpdata_assert(self, args, output, format='json', natural_keys=False,
exclude_list=[]): use_base_manager=False, exclude_list=[]):
new_io = StringIO.StringIO() new_io = StringIO.StringIO()
management.call_command('dumpdata', *args, **{'format':format, management.call_command('dumpdata', *args, **{'format':format,
'stdout':new_io, 'stdout':new_io,
'stderr':new_io, 'stderr':new_io,
'use_natural_keys':natural_keys, 'use_natural_keys':natural_keys,
'use_base_manager':use_base_manager,
'exclude': exclude_list}) 'exclude': exclude_list})
command_output = new_io.getvalue().strip() command_output = new_io.getvalue().strip()
self.assertEqual(command_output, output) self.assertEqual(command_output, output)
@ -197,6 +198,17 @@ class FixtureLoadingTests(TestCase):
'', '',
exclude_list=['fixtures.FooModel']) 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(),
['<Spy: Paul>'])
# 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): 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, commit=False) management.call_command('loaddata', 'fixture4.json', verbosity=0, commit=False)