Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #14068 -- Corrected error handling in loaddata when an allow_sy…

…ncdb method is defined on the router. Thanks to Xavier Ordoquy for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13612 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit c2e3ba3ba0bf6cca0a35d904b334a37b225a31da 1 parent e0387f7
Russell Keith-Magee authored August 20, 2010
27  django/core/management/commands/loaddata.py
@@ -47,7 +47,8 @@ def handle(self, *fixture_labels, **options):
47 47
 
48 48
         # Keep a count of the installed objects and fixtures
49 49
         fixture_count = 0
50  
-        object_count = 0
  50
+        loaded_object_count = 0
  51
+        fixture_object_count = 0
51 52
         models = set()
52 53
 
53 54
         humanize = lambda dirname: dirname and "'%s'" % dirname or 'absolute path'
@@ -114,7 +115,7 @@ def read(self):
114 115
                 if verbosity >= 2:
115 116
                     self.stdout.write("Loading '%s' fixtures...\n" % fixture_name)
116 117
             else:
117  
-                sys.stderr.write(
  118
+                self.stderr.write(
118 119
                     self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format.\n" %
119 120
                         (fixture_name, format)))
120 121
                 transaction.rollback(using=using)
@@ -157,17 +158,20 @@ def read(self):
157 158
                         else:
158 159
                             fixture_count += 1
159 160
                             objects_in_fixture = 0
  161
+                            loaded_objects_in_fixture = 0
160 162
                             if verbosity >= 2:
161 163
                                 self.stdout.write("Installing %s fixture '%s' from %s.\n" % \
162 164
                                     (format, fixture_name, humanize(fixture_dir)))
163 165
                             try:
164 166
                                 objects = serializers.deserialize(format, fixture, using=using)
165 167
                                 for obj in objects:
  168
+                                    objects_in_fixture += 1
166 169
                                     if router.allow_syncdb(using, obj.object.__class__):
167  
-                                        objects_in_fixture += 1
  170
+                                        loaded_objects_in_fixture += 1
168 171
                                         models.add(obj.object.__class__)
169 172
                                         obj.save(using=using)
170  
-                                object_count += objects_in_fixture
  173
+                                loaded_object_count += loaded_objects_in_fixture
  174
+                                fixture_object_count += objects_in_fixture
171 175
                                 label_found = True
172 176
                             except (SystemExit, KeyboardInterrupt):
173 177
                                 raise
@@ -179,7 +183,7 @@ def read(self):
179 183
                                 if show_traceback:
180 184
                                     traceback.print_exc()
181 185
                                 else:
182  
-                                    sys.stderr.write(
  186
+                                    self.stderr.write(
183 187
                                         self.style.ERROR("Problem installing fixture '%s': %s\n" %
184 188
                                              (full_path, ''.join(traceback.format_exception(sys.exc_type,
185 189
                                                  sys.exc_value, sys.exc_traceback)))))
@@ -189,7 +193,7 @@ def read(self):
189 193
                             # If the fixture we loaded contains 0 objects, assume that an
190 194
                             # error was encountered during fixture loading.
191 195
                             if objects_in_fixture == 0:
192  
-                                sys.stderr.write(
  196
+                                self.stderr.write(
193 197
                                     self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)\n" %
194 198
                                         (fixture_name)))
195 199
                                 transaction.rollback(using=using)
@@ -203,7 +207,7 @@ def read(self):
203 207
 
204 208
         # If we found even one object in a fixture, we need to reset the
205 209
         # database sequences.
206  
-        if object_count > 0:
  210
+        if loaded_object_count > 0:
207 211
             sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
208 212
             if sequence_sql:
209 213
                 if verbosity >= 2:
@@ -215,12 +219,17 @@ def read(self):
215 219
             transaction.commit(using=using)
216 220
             transaction.leave_transaction_management(using=using)
217 221
 
218  
-        if object_count == 0:
  222
+        if fixture_object_count == 0:
219 223
             if verbosity >= 1:
220 224
                 self.stdout.write("No fixtures found.\n")
221 225
         else:
222 226
             if verbosity >= 1:
223  
-                self.stdout.write("Installed %d object(s) from %d fixture(s)\n" % (object_count, fixture_count))
  227
+                if fixture_object_count == loaded_object_count:
  228
+                    self.stdout.write("Installed %d object(s) from %d fixture(s)\n" % (
  229
+                        loaded_object_count, fixture_count))
  230
+                else:
  231
+                    self.stdout.write("Installed %d object(s) (of %d) from %d fixture(s)\n" % (
  232
+                        loaded_object_count, fixture_object_count, fixture_count))
224 233
 
225 234
         # Close the DB connection. This is required as a workaround for an
226 235
         # edge case in MySQL: if the same connection is used to
18  tests/regressiontests/multiple_database/fixtures/pets.json
... ...
@@ -0,0 +1,18 @@
  1
+[
  2
+    {
  3
+        "pk": 1,
  4
+        "model": "multiple_database.pet",
  5
+        "fields": {
  6
+            "name": "Mr Bigglesworth",
  7
+            "owner": 1
  8
+        }
  9
+    },
  10
+    {
  11
+        "pk": 2,
  12
+        "model": "multiple_database.pet",
  13
+        "fields": {
  14
+            "name": "Spot",
  15
+            "owner": 2
  16
+        }
  17
+    }
  18
+]
28  tests/regressiontests/multiple_database/tests.py
@@ -1570,11 +1570,31 @@ def test_user_profiles(self):
1570 1570
         self.assertEquals(alice.get_profile().flavor, 'chocolate')
1571 1571
         self.assertEquals(bob.get_profile().flavor, 'crunchy frog')
1572 1572
 
  1573
+class AntiPetRouter(object):
  1574
+    # A router that only expresses an opinion on syncdb,
  1575
+    # passing pets to the 'other' database
  1576
+
  1577
+    def allow_syncdb(self, db, model):
  1578
+        "Make sure the auth app only appears on the 'other' db"
  1579
+        if db == 'other':
  1580
+            return model._meta.object_name == 'Pet'
  1581
+        else:
  1582
+            return model._meta.object_name != 'Pet'
  1583
+        return None
1573 1584
 
1574 1585
 class FixtureTestCase(TestCase):
1575 1586
     multi_db = True
1576 1587
     fixtures = ['multidb-common', 'multidb']
1577 1588
 
  1589
+    def setUp(self):
  1590
+        # Install the anti-pet router
  1591
+        self.old_routers = router.routers
  1592
+        router.routers = [AntiPetRouter()]
  1593
+
  1594
+    def tearDown(self):
  1595
+        # Restore the 'other' database as an independent database
  1596
+        router.routers = self.old_routers
  1597
+
1578 1598
     def test_fixture_loading(self):
1579 1599
         "Multi-db fixtures are loaded correctly"
1580 1600
         # Check that "Pro Django" exists on the default database, but not on other database
@@ -1612,6 +1632,14 @@ def test_fixture_loading(self):
1612 1632
         except Book.DoesNotExist:
1613 1633
             self.fail('"The Definitive Guide to Django" should exist on both databases')
1614 1634
 
  1635
+    def test_pseudo_empty_fixtures(self):
  1636
+        "A fixture can contain entries, but lead to nothing in the database; this shouldn't raise an error (ref #14068)"
  1637
+        new_io = StringIO()
  1638
+        management.call_command('loaddata', 'pets', stdout=new_io, stderr=new_io)
  1639
+        command_output = new_io.getvalue().strip()
  1640
+        # No objects will actually be loaded
  1641
+        self.assertEqual(command_output, "Installed 0 object(s) (of 2) from 1 fixture(s)")
  1642
+
1615 1643
 class PickleQuerySetTestCase(TestCase):
1616 1644
     multi_db = True
1617 1645
 

0 notes on commit c2e3ba3

Please sign in to comment.
Something went wrong with that request. Please try again.