Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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.
  • Loading branch information...
commit 6786920fd8a1dfa43bba8333548c2496847298af 1 parent bdde7fe
@ptone ptone authored
View
21 django/core/management/commands/dumpdata.py
@@ -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=[],
@fruit
fruit added a note

IMHO, the make_option arguments should be:

make_option('--pks', dest='primary_keys', default='', ...

otherwise, you will get the error:

File "django/core/management/commands/dumpdata.py", line 45, in handle primary_keys = pks.split(',')
AttributeError: 'list' object has no attribute 'split'

it happens to me when I run:

python manage.py dumpdata appname appname.appmodel  --pks "1,8,10"

it's odd to me, that your tests did not detect it

@ptone Collaborator
ptone added a note

indeed - this looks like it was originally written for --pks=1 --pks=4 --pks=10 style appending, but as documented uses comma delimited.

The tests didn't get hung up on this, as they bypass the optparse bits and run the management command directly.

I'll push a fix for this shortly.

@ptone Collaborator
ptone added a note

clearly already done: 5923581 ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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 @@ def handle(self, *app_labels, **options):
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 @@ def handle(self, *app_labels, **options):
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 @@ def handle(self, *app_labels, **options):
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 @@ def get_objects():
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:
View
9 docs/ref/django-admin.txt
@@ -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
-----
View
4 docs/releases/1.6.txt
@@ -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
=====================================
View
44 tests/fixtures/tests.py
@@ -27,14 +27,15 @@ def testClassFixtures(self):
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 @@ def test_dumpdata_with_filtering_manager(self):
# 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)
Please sign in to comment.
Something went wrong with that request. Please try again.