Fixed #16330 -- added --pks option in dumpdata command
Thanks to guettli for the initial ticket and patch, with additional work from mehmetakyuz and Kevin Brolly.
This commit is contained in:
parent
bdde7feb26
commit
6786920fd8
|
@ -21,6 +21,8 @@ class Command(BaseCommand):
|
||||||
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,
|
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="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."),
|
||||||
|
make_option('--pks', dest='primary_keys', action='append', default=[],
|
||||||
|
help="Only dump objects with given primary keys. Accepts a comma seperated list of keys. This option will only work when you specify one model."),
|
||||||
)
|
)
|
||||||
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 "
|
||||||
|
@ -37,6 +39,12 @@ class Command(BaseCommand):
|
||||||
show_traceback = options.get('traceback')
|
show_traceback = options.get('traceback')
|
||||||
use_natural_keys = options.get('use_natural_keys')
|
use_natural_keys = options.get('use_natural_keys')
|
||||||
use_base_manager = options.get('use_base_manager')
|
use_base_manager = options.get('use_base_manager')
|
||||||
|
pks = options.get('primary_keys')
|
||||||
|
|
||||||
|
if pks:
|
||||||
|
primary_keys = pks.split(',')
|
||||||
|
else:
|
||||||
|
primary_keys = False
|
||||||
|
|
||||||
excluded_apps = set()
|
excluded_apps = set()
|
||||||
excluded_models = set()
|
excluded_models = set()
|
||||||
|
@ -55,8 +63,12 @@ class Command(BaseCommand):
|
||||||
raise CommandError('Unknown app in excludes: %s' % exclude)
|
raise CommandError('Unknown app in excludes: %s' % exclude)
|
||||||
|
|
||||||
if len(app_labels) == 0:
|
if len(app_labels) == 0:
|
||||||
|
if primary_keys:
|
||||||
|
raise CommandError("You can only use --pks option with one model")
|
||||||
app_list = SortedDict((app, None) for app in get_apps() if app not in excluded_apps)
|
app_list = SortedDict((app, None) for app in get_apps() if app not in excluded_apps)
|
||||||
else:
|
else:
|
||||||
|
if len(app_labels) > 1 and primary_keys:
|
||||||
|
raise CommandError("You can only use --pks option with one model")
|
||||||
app_list = SortedDict()
|
app_list = SortedDict()
|
||||||
for label in app_labels:
|
for label in app_labels:
|
||||||
try:
|
try:
|
||||||
|
@ -77,6 +89,8 @@ class Command(BaseCommand):
|
||||||
else:
|
else:
|
||||||
app_list[app] = [model]
|
app_list[app] = [model]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
if primary_keys:
|
||||||
|
raise CommandError("You can only use --pks option with one model")
|
||||||
# This is just an app - no model qualifier
|
# This is just an app - no model qualifier
|
||||||
app_label = label
|
app_label = label
|
||||||
try:
|
try:
|
||||||
|
@ -107,8 +121,11 @@ class Command(BaseCommand):
|
||||||
objects = model._base_manager
|
objects = model._base_manager
|
||||||
else:
|
else:
|
||||||
objects = model._default_manager
|
objects = model._default_manager
|
||||||
for obj in objects.using(using).\
|
|
||||||
order_by(model._meta.pk.name).iterator():
|
queryset = objects.using(using).order_by(model._meta.pk.name)
|
||||||
|
if primary_keys:
|
||||||
|
queryset = queryset.filter(pk__in=primary_keys)
|
||||||
|
for obj in queryset.iterator():
|
||||||
yield obj
|
yield obj
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -227,6 +227,15 @@ a natural key definition. If you are dumping ``contrib.auth`` ``Permission``
|
||||||
objects or ``contrib.contenttypes`` ``ContentType`` objects, you should
|
objects or ``contrib.contenttypes`` ``ContentType`` objects, you should
|
||||||
probably be using this flag.
|
probably be using this flag.
|
||||||
|
|
||||||
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
|
.. django-admin-option:: --pks
|
||||||
|
|
||||||
|
By default, ``dumpdata`` will output all the records of the model, but
|
||||||
|
you can use the ``--pks`` option to specify a comma seperated list of
|
||||||
|
primary keys on which to filter. This is only available when dumping
|
||||||
|
one model.
|
||||||
|
|
||||||
flush
|
flush
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,10 @@ Minor features
|
||||||
and :func:`~django.contrib.auth.views.password_change`, you can now pass
|
and :func:`~django.contrib.auth.views.password_change`, you can now pass
|
||||||
URL names and they will be resolved.
|
URL names and they will be resolved.
|
||||||
|
|
||||||
|
* The ``dumpdata`` manage.py command now has a --pks option which will
|
||||||
|
allow users to specify the primary keys of objects they want to dump.
|
||||||
|
This option can only be used with one model.
|
||||||
|
|
||||||
Backwards incompatible changes in 1.6
|
Backwards incompatible changes in 1.6
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
|
|
@ -27,14 +27,15 @@ class TestCaseFixtureLoadingTests(TestCase):
|
||||||
class DumpDataAssertMixin(object):
|
class DumpDataAssertMixin(object):
|
||||||
|
|
||||||
def _dumpdata_assert(self, args, output, format='json', natural_keys=False,
|
def _dumpdata_assert(self, args, output, format='json', natural_keys=False,
|
||||||
use_base_manager=False, exclude_list=[]):
|
use_base_manager=False, exclude_list=[], primary_keys=[]):
|
||||||
new_io = six.StringIO()
|
new_io = six.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,
|
'use_base_manager': use_base_manager,
|
||||||
'exclude': exclude_list})
|
'exclude': exclude_list,
|
||||||
|
'primary_keys': primary_keys})
|
||||||
command_output = new_io.getvalue().strip()
|
command_output = new_io.getvalue().strip()
|
||||||
if format == "json":
|
if format == "json":
|
||||||
self.assertJSONEqual(command_output, output)
|
self.assertJSONEqual(command_output, output)
|
||||||
|
@ -223,6 +224,45 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase):
|
||||||
# even those normally filtered by the manager
|
# even those normally filtered by the manager
|
||||||
self._dumpdata_assert(['fixtures.Spy'], '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": true}}, {"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % (spy2.pk, spy1.pk), use_base_manager=True)
|
self._dumpdata_assert(['fixtures.Spy'], '[{"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": true}}, {"pk": %d, "model": "fixtures.spy", "fields": {"cover_blown": false}}]' % (spy2.pk, spy1.pk), use_base_manager=True)
|
||||||
|
|
||||||
|
def test_dumpdata_with_pks(self):
|
||||||
|
management.call_command('loaddata', 'fixture1.json', verbosity=0, commit=False)
|
||||||
|
management.call_command('loaddata', 'fixture2.json', verbosity=0, commit=False)
|
||||||
|
self._dumpdata_assert(
|
||||||
|
['fixtures.Article'],
|
||||||
|
'[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]',
|
||||||
|
primary_keys='2,3'
|
||||||
|
)
|
||||||
|
|
||||||
|
self._dumpdata_assert(
|
||||||
|
['fixtures.Article'],
|
||||||
|
'[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}]',
|
||||||
|
primary_keys='2'
|
||||||
|
)
|
||||||
|
|
||||||
|
with six.assertRaisesRegex(self, management.CommandError,
|
||||||
|
"You can only use --pks option with one model"):
|
||||||
|
self._dumpdata_assert(
|
||||||
|
['fixtures'],
|
||||||
|
'[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]',
|
||||||
|
primary_keys='2,3'
|
||||||
|
)
|
||||||
|
|
||||||
|
with six.assertRaisesRegex(self, management.CommandError,
|
||||||
|
"You can only use --pks option with one model"):
|
||||||
|
self._dumpdata_assert(
|
||||||
|
'',
|
||||||
|
'[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]',
|
||||||
|
primary_keys='2,3'
|
||||||
|
)
|
||||||
|
|
||||||
|
with six.assertRaisesRegex(self, management.CommandError,
|
||||||
|
"You can only use --pks option with one model"):
|
||||||
|
self._dumpdata_assert(
|
||||||
|
['fixtures.Article', 'fixtures.category'],
|
||||||
|
'[{"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Copyright is fine the way it is", "pub_date": "2006-06-16T14:00:00"}}]',
|
||||||
|
primary_keys='2,3'
|
||||||
|
)
|
||||||
|
|
||||||
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)
|
||||||
|
|
Loading…
Reference in New Issue