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.'),
|
||||
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."),
|
||||
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 "
|
||||
"format (using each model's default manager unless --all is "
|
||||
|
@ -37,6 +39,12 @@ class Command(BaseCommand):
|
|||
show_traceback = options.get('traceback')
|
||||
use_natural_keys = options.get('use_natural_keys')
|
||||
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_models = set()
|
||||
|
@ -55,8 +63,12 @@ class Command(BaseCommand):
|
|||
raise CommandError('Unknown app in excludes: %s' % exclude)
|
||||
|
||||
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)
|
||||
else:
|
||||
if len(app_labels) > 1 and primary_keys:
|
||||
raise CommandError("You can only use --pks option with one model")
|
||||
app_list = SortedDict()
|
||||
for label in app_labels:
|
||||
try:
|
||||
|
@ -77,6 +89,8 @@ class Command(BaseCommand):
|
|||
else:
|
||||
app_list[app] = [model]
|
||||
except ValueError:
|
||||
if primary_keys:
|
||||
raise CommandError("You can only use --pks option with one model")
|
||||
# This is just an app - no model qualifier
|
||||
app_label = label
|
||||
try:
|
||||
|
@ -107,8 +121,11 @@ class Command(BaseCommand):
|
|||
objects = model._base_manager
|
||||
else:
|
||||
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
|
||||
|
||||
try:
|
||||
|
|
|
@ -227,6 +227,15 @@ a natural key definition. If you are dumping ``contrib.auth`` ``Permission``
|
|||
objects or ``contrib.contenttypes`` ``ContentType`` objects, you should
|
||||
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
|
||||
-----
|
||||
|
||||
|
|
|
@ -249,6 +249,10 @@ Minor features
|
|||
and :func:`~django.contrib.auth.views.password_change`, you can now pass
|
||||
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
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -27,14 +27,15 @@ class TestCaseFixtureLoadingTests(TestCase):
|
|||
class DumpDataAssertMixin(object):
|
||||
|
||||
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()
|
||||
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})
|
||||
'exclude': exclude_list,
|
||||
'primary_keys': primary_keys})
|
||||
command_output = new_io.getvalue().strip()
|
||||
if format == "json":
|
||||
self.assertJSONEqual(command_output, output)
|
||||
|
@ -223,6 +224,45 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase):
|
|||
# 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)
|
||||
|
||||
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):
|
||||
# Load fixture 4 (compressed), using format specification
|
||||
management.call_command('loaddata', 'fixture4.json', verbosity=0, commit=False)
|
||||
|
|
Loading…
Reference in New Issue