Fixed #23372 -- Made loaddata faster if it doesn't find any fixtures.
Django's test suite often tries to load fixture files from apps that have no fixtures at all. This creates a lot of unnecessary disabling and enabling of constraints which can be expensive on some database. To speed this up, loaddata now first checks if any fixture file matches. If no fixture file is matched, then the command exits before disabling and enabling of constraints is done. The main benefit of this change is seen on MSSQL, where tests on Django 1.8 run hours faster.
This commit is contained in:
parent
6687f4dcbb
commit
ee9f4686b1
|
@ -85,6 +85,16 @@ class Command(BaseCommand):
|
||||||
if has_bz2:
|
if has_bz2:
|
||||||
self.compression_formats['bz2'] = (bz2.BZ2File, 'r')
|
self.compression_formats['bz2'] = (bz2.BZ2File, 'r')
|
||||||
|
|
||||||
|
# Django's test suite repeatedly tries to load initial_data fixtures
|
||||||
|
# from apps that don't have any fixtures. Because disabling constraint
|
||||||
|
# checks can be expensive on some database (especially MSSQL), bail
|
||||||
|
# out early if no fixtures are found.
|
||||||
|
for fixture_label in fixture_labels:
|
||||||
|
if self.find_fixtures(fixture_label):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
with connection.constraint_checks_disabled():
|
with connection.constraint_checks_disabled():
|
||||||
for fixture_label in fixture_labels:
|
for fixture_label in fixture_labels:
|
||||||
self.load_label(fixture_label)
|
self.load_label(fixture_label)
|
||||||
|
|
|
@ -51,3 +51,6 @@ Bugfixes
|
||||||
|
|
||||||
* Fixed a regression in the admin which ignored line breaks in read-only fields
|
* Fixed a regression in the admin which ignored line breaks in read-only fields
|
||||||
instead of converting them to ``<br>`` (:ticket:`25465`).
|
instead of converting them to ``<br>`` (:ticket:`25465`).
|
||||||
|
|
||||||
|
* Made ``loaddata`` skip disabling and enabling database constraints when it
|
||||||
|
doesn't load any fixtures (:ticket:`23372`).
|
||||||
|
|
|
@ -73,3 +73,6 @@ Bugfixes
|
||||||
|
|
||||||
* Fixed incorrect object reference in
|
* Fixed incorrect object reference in
|
||||||
``SingleObjectMixin.get_context_object_name()`` (:ticket:`26006`).
|
``SingleObjectMixin.get_context_object_name()`` (:ticket:`26006`).
|
||||||
|
|
||||||
|
* Made ``loaddata`` skip disabling and enabling database constraints when it
|
||||||
|
doesn't load any fixtures (:ticket:`23372`).
|
||||||
|
|
|
@ -13,7 +13,7 @@ from django.core.files.temp import NamedTemporaryFile
|
||||||
from django.core.serializers.base import ProgressBar
|
from django.core.serializers.base import ProgressBar
|
||||||
from django.db import IntegrityError, connection
|
from django.db import IntegrityError, connection
|
||||||
from django.test import (
|
from django.test import (
|
||||||
TestCase, TransactionTestCase, ignore_warnings, skipUnlessDBFeature,
|
TestCase, TransactionTestCase, ignore_warnings, mock, skipUnlessDBFeature,
|
||||||
)
|
)
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
@ -643,6 +643,18 @@ class NonExistentFixtureTests(TestCase):
|
||||||
self.assertEqual(force_text(w[0].message),
|
self.assertEqual(force_text(w[0].message),
|
||||||
"No fixture named 'this_fixture_doesnt_exist' found.")
|
"No fixture named 'this_fixture_doesnt_exist' found.")
|
||||||
|
|
||||||
|
@mock.patch('django.db.connection.enable_constraint_checking')
|
||||||
|
@mock.patch('django.db.connection.disable_constraint_checking')
|
||||||
|
def test_nonexistent_fixture_no_constraint_checking(self,
|
||||||
|
disable_constraint_checking, enable_constraint_checking):
|
||||||
|
"""
|
||||||
|
If no fixtures match the loaddata command, constraints checks on the
|
||||||
|
database shouldn't be disabled. This is performance critical on MSSQL.
|
||||||
|
"""
|
||||||
|
management.call_command('loaddata', 'this_fixture_doesnt_exist', verbosity=0)
|
||||||
|
disable_constraint_checking.assert_not_called()
|
||||||
|
enable_constraint_checking.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
class FixtureTransactionTests(DumpDataAssertMixin, TransactionTestCase):
|
class FixtureTransactionTests(DumpDataAssertMixin, TransactionTestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue