Ticket #17530: 17530_fix_and_tests.diff

File 17530_fix_and_tests.diff, 15.5 KB (added by lukeplant, 3 years ago)

corrected patch, hopefully, with tests

  • django/core/management/commands/loaddata.py

    diff -r a729bd009e06 django/core/management/commands/loaddata.py
    a b  
    104104                app_module_paths.append(app.__file__)
    105105
    106106        app_fixtures = [os.path.join(os.path.dirname(path), 'fixtures') for path in app_module_paths]
    107         for fixture_label in fixture_labels:
    108             parts = fixture_label.split('.')
    109107
    110             if len(parts) > 1 and parts[-1] in compression_types:
    111                 compression_formats = [parts[-1]]
    112                 parts = parts[:-1]
    113             else:
    114                 compression_formats = compression_types.keys()
     108        try:
     109            with connection.constraint_checks_disabled():
     110                for fixture_label in fixture_labels:
     111                    parts = fixture_label.split('.')
    115112
    116             if len(parts) == 1:
    117                 fixture_name = parts[0]
    118                 formats = serializers.get_public_serializer_formats()
    119             else:
    120                 fixture_name, format = '.'.join(parts[:-1]), parts[-1]
    121                 if format in serializers.get_public_serializer_formats():
    122                     formats = [format]
    123                 else:
    124                     formats = []
     113                    if len(parts) > 1 and parts[-1] in compression_types:
     114                        compression_formats = [parts[-1]]
     115                        parts = parts[:-1]
     116                    else:
     117                        compression_formats = compression_types.keys()
    125118
    126             if formats:
    127                 if verbosity >= 2:
    128                     self.stdout.write("Loading '%s' fixtures...\n" % fixture_name)
    129             else:
    130                 self.stderr.write(
    131                     self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format.\n" %
    132                         (fixture_name, format)))
    133                 if commit:
    134                     transaction.rollback(using=using)
    135                     transaction.leave_transaction_management(using=using)
    136                 return
     119                    if len(parts) == 1:
     120                        fixture_name = parts[0]
     121                        formats = serializers.get_public_serializer_formats()
     122                    else:
     123                        fixture_name, format = '.'.join(parts[:-1]), parts[-1]
     124                        if format in serializers.get_public_serializer_formats():
     125                            formats = [format]
     126                        else:
     127                            formats = []
    137128
    138             if os.path.isabs(fixture_name):
    139                 fixture_dirs = [fixture_name]
    140             else:
    141                 fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + ['']
     129                    if formats:
     130                        if verbosity >= 2:
     131                            self.stdout.write("Loading '%s' fixtures...\n" % fixture_name)
     132                    else:
     133                        self.stderr.write(
     134                            self.style.ERROR("Problem installing fixture '%s': %s is not a known serialization format.\n" %
     135                                (fixture_name, format)))
     136                        if commit:
     137                            transaction.rollback(using=using)
     138                            transaction.leave_transaction_management(using=using)
     139                        return
    142140
    143             for fixture_dir in fixture_dirs:
    144                 if verbosity >= 2:
    145                     self.stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir))
     141                    if os.path.isabs(fixture_name):
     142                        fixture_dirs = [fixture_name]
     143                    else:
     144                        fixture_dirs = app_fixtures + list(settings.FIXTURE_DIRS) + ['']
    146145
    147                 label_found = False
    148                 for combo in product([using, None], formats, compression_formats):
    149                     database, format, compression_format = combo
    150                     file_name = '.'.join(
    151                         p for p in [
    152                             fixture_name, database, format, compression_format
    153                         ]
    154                         if p
    155                     )
     146                    for fixture_dir in fixture_dirs:
     147                        if verbosity >= 2:
     148                            self.stdout.write("Checking %s for fixtures...\n" % humanize(fixture_dir))
    156149
    157                     if verbosity >= 3:
    158                         self.stdout.write("Trying %s for %s fixture '%s'...\n" % \
    159                             (humanize(fixture_dir), file_name, fixture_name))
    160                     full_path = os.path.join(fixture_dir, file_name)
    161                     open_method = compression_types[compression_format]
    162                     try:
    163                         fixture = open_method(full_path, 'r')
    164                     except IOError:
    165                         if verbosity >= 2:
    166                             self.stdout.write("No %s fixture '%s' in %s.\n" % \
    167                                 (format, fixture_name, humanize(fixture_dir)))
    168                     else:
    169                         if label_found:
    170                             fixture.close()
    171                             self.stderr.write(self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting.\n" %
    172                                 (fixture_name, humanize(fixture_dir))))
    173                             if commit:
    174                                 transaction.rollback(using=using)
    175                                 transaction.leave_transaction_management(using=using)
    176                             return
    177                         else:
    178                             fixture_count += 1
    179                             objects_in_fixture = 0
    180                             loaded_objects_in_fixture = 0
    181                             if verbosity >= 2:
    182                                 self.stdout.write("Installing %s fixture '%s' from %s.\n" % \
    183                                     (format, fixture_name, humanize(fixture_dir)))
     150                        label_found = False
     151                        for combo in product([using, None], formats, compression_formats):
     152                            database, format, compression_format = combo
     153                            file_name = '.'.join(
     154                                p for p in [
     155                                    fixture_name, database, format, compression_format
     156                                ]
     157                                if p
     158                            )
     159
     160                            if verbosity >= 3:
     161                                self.stdout.write("Trying %s for %s fixture '%s'...\n" % \
     162                                    (humanize(fixture_dir), file_name, fixture_name))
     163                            full_path = os.path.join(fixture_dir, file_name)
     164                            open_method = compression_types[compression_format]
    184165                            try:
    185                                 objects = serializers.deserialize(format, fixture, using=using)
     166                                fixture = open_method(full_path, 'r')
     167                            except IOError:
     168                                if verbosity >= 2:
     169                                    self.stdout.write("No %s fixture '%s' in %s.\n" % \
     170                                        (format, fixture_name, humanize(fixture_dir)))
     171                            else:
     172                                try:
     173                                    if label_found:
     174                                        self.stderr.write(self.style.ERROR("Multiple fixtures named '%s' in %s. Aborting.\n" %
     175                                            (fixture_name, humanize(fixture_dir))))
     176                                        if commit:
     177                                            transaction.rollback(using=using)
     178                                            transaction.leave_transaction_management(using=using)
     179                                        return
    186180
    187                                 with connection.constraint_checks_disabled():
     181                                    fixture_count += 1
     182                                    objects_in_fixture = 0
     183                                    loaded_objects_in_fixture = 0
     184                                    if verbosity >= 2:
     185                                        self.stdout.write("Installing %s fixture '%s' from %s.\n" % \
     186                                            (format, fixture_name, humanize(fixture_dir)))
     187
     188                                    objects = serializers.deserialize(format, fixture, using=using)
     189
    188190                                    for obj in objects:
    189191                                        objects_in_fixture += 1
    190192                                        if router.allow_syncdb(using, obj.object.__class__):
     
    201203                                                    }
    202204                                                raise e.__class__, e.__class__(msg), sys.exc_info()[2]
    203205
    204                                 # Since we disabled constraint checks, we must manually check for
    205                                 # any invalid keys that might have been added
    206                                 table_names = [model._meta.db_table for model in models]
    207                                 connection.check_constraints(table_names=table_names)
     206                                    loaded_object_count += loaded_objects_in_fixture
     207                                    fixture_object_count += objects_in_fixture
     208                                    label_found = True
     209                                finally:
     210                                    fixture.close()
    208211
    209                                 loaded_object_count += loaded_objects_in_fixture
    210                                 fixture_object_count += objects_in_fixture
    211                                 label_found = True
    212                             except (SystemExit, KeyboardInterrupt):
    213                                 raise
    214                             except Exception:
    215                                 fixture.close()
    216                                 if commit:
    217                                     transaction.rollback(using=using)
    218                                     transaction.leave_transaction_management(using=using)
    219                                 if show_traceback:
    220                                     traceback.print_exc()
    221                                 else:
     212                                # If the fixture we loaded contains 0 objects, assume that an
     213                                # error was encountered during fixture loading.
     214                                if objects_in_fixture == 0:
    222215                                    self.stderr.write(
    223                                         self.style.ERROR("Problem installing fixture '%s': %s\n" %
    224                                              (full_path, ''.join(traceback.format_exception(sys.exc_type,
    225                                                  sys.exc_value, sys.exc_traceback)))))
    226                                 return
    227                             fixture.close()
     216                                        self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)\n" %
     217                                            (fixture_name)))
     218                                    if commit:
     219                                        transaction.rollback(using=using)
     220                                        transaction.leave_transaction_management(using=using)
     221                                    return
    228222
    229                             # If the fixture we loaded contains 0 objects, assume that an
    230                             # error was encountered during fixture loading.
    231                             if objects_in_fixture == 0:
    232                                 self.stderr.write(
    233                                     self.style.ERROR("No fixture data found for '%s'. (File format may be invalid.)\n" %
    234                                         (fixture_name)))
    235                                 if commit:
    236                                     transaction.rollback(using=using)
    237                                     transaction.leave_transaction_management(using=using)
    238                                 return
     223            # Since we disabled constraint checks, we must manually check for
     224            # any invalid keys that might have been added
     225            table_names = [model._meta.db_table for model in models]
     226            connection.check_constraints(table_names=table_names)
     227
     228        except (SystemExit, KeyboardInterrupt):
     229            raise
     230        except Exception:
     231            if commit:
     232                transaction.rollback(using=using)
     233                transaction.leave_transaction_management(using=using)
     234            if show_traceback:
     235                traceback.print_exc()
     236            else:
     237                self.stderr.write(
     238                    self.style.ERROR("Problem installing fixture '%s': %s\n" %
     239                         (full_path, ''.join(traceback.format_exception(sys.exc_type,
     240                             sys.exc_value, sys.exc_traceback)))))
     241            return
     242
    239243
    240244        # If we found even one object in a fixture, we need to reset the
    241245        # database sequences.
  • new file tests/regressiontests/fixtures_regress/fixtures_1/forward_ref_1.json

    diff -r a729bd009e06 tests/regressiontests/fixtures_regress/fixtures_1/forward_ref_1.json
    - +  
     1[
     2    {
     3        "pk": 1,
     4        "model": "fixtures_regress.book",
     5        "fields": {
     6            "name": "Cryptonomicon",
     7            "author": 4
     8        }
     9    }
     10]
  • new file tests/regressiontests/fixtures_regress/fixtures_2/forward_ref_2.json

    diff -r a729bd009e06 tests/regressiontests/fixtures_regress/fixtures_2/forward_ref_2.json
    - +  
     1[
     2    {
     3        "pk": "4",
     4        "model": "fixtures_regress.person",
     5        "fields": {
     6            "name": "Neal Stephenson"
     7        }
     8    }
     9]
  • tests/regressiontests/fixtures_regress/tests.py

    diff -r a729bd009e06 tests/regressiontests/fixtures_regress/tests.py
    a b  
    1616from django.db.models import signals
    1717from django.test import (TestCase, TransactionTestCase, skipIfDBFeature,
    1818    skipUnlessDBFeature)
     19from django.test.utils import override_settings
    1920
    2021from .models import (Animal, Stuff, Absolute, Parent, Child, Article, Widget,
    2122    Store, Person, Book, NKChild, RefToNKChild, Circle1, Circle2, Circle3,
     
    390391            stderr.getvalue().startswith('Problem installing fixture')
    391392        )
    392393
     394    _cur_dir = os.path.dirname(os.path.abspath(__file__))
     395
     396    @override_settings(FIXTURE_DIRS=[os.path.join(_cur_dir, 'fixtures_1'),
     397                                     os.path.join(_cur_dir, 'fixtures_2')])
     398    def test_loaddata_forward_refs_split_fixtures(self):
     399        """
     400        Regression for #17530 - should be able to cope with forward references
     401        when the fixtures are not in the same files or directories.
     402        """
     403        management.call_command(
     404            'loaddata',
     405            'forward_ref_1.json',
     406            'forward_ref_2.json',
     407            verbosity=0,
     408            commit=False
     409        )
     410        self.assertEqual(Book.objects.all()[0].id, 1)
     411        self.assertEqual(Person.objects.all()[0].id, 4)
     412
    393413    def test_loaddata_no_fixture_specified(self):
    394414        """
    395415        Regression for #7043 - Error is quickly reported when no fixtures is provided in the command line.
Back to Top