summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPreston Holmes <preston@ptone.com>2013-05-19 12:39:14 +0200
committerPreston Holmes <preston@ptone.com>2013-05-19 09:10:40 -0700
commit6786920fd8a1dfa43bba8333548c2496847298af (patch)
tree572ca38edf73ec30095bd25f691b6879b230dfc1
parentbdde7feb26f89e580c2b21154196fe3f8c774677 (diff)
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.
-rw-r--r--django/core/management/commands/dumpdata.py21
-rw-r--r--docs/ref/django-admin.txt9
-rw-r--r--docs/releases/1.6.txt4
-rw-r--r--tests/fixtures/tests.py44
4 files changed, 74 insertions, 4 deletions
diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py
index d3650b1eb8..b1e06e4255 100644
--- a/django/core/management/commands/dumpdata.py
+++ b/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=[],
+ 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:
diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
index 2f2880679c..e193a448d2 100644
--- a/docs/ref/django-admin.txt
+++ b/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
-----
diff --git a/docs/releases/1.6.txt b/docs/releases/1.6.txt
index a6244498f2..9950717420 100644
--- a/docs/releases/1.6.txt
+++ b/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
=====================================
diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py
index f954933046..e32522b929 100644
--- a/tests/fixtures/tests.py
+++ b/tests/fixtures/tests.py
@@ -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)