mirror of https://github.com/django/django.git
Fixed #23468 -- Added checks for duplicate fixtures directories in loaddata.
If settings.FIXTURE_DIRS contains duplicates or a default fixture directory (app_name/fixtures), ImproperlyConfigured is raised. Thanks to Berker Peksag and Tim Graham for review.
This commit is contained in:
parent
e548d08f24
commit
934a16dc93
|
@ -9,6 +9,7 @@ import zipfile
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.management.base import BaseCommand, CommandError
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
from django.core.management.color import no_style
|
from django.core.management.color import no_style
|
||||||
from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
|
from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
|
||||||
|
@ -238,13 +239,23 @@ class Command(BaseCommand):
|
||||||
current directory.
|
current directory.
|
||||||
"""
|
"""
|
||||||
dirs = []
|
dirs = []
|
||||||
|
fixture_dirs = settings.FIXTURE_DIRS
|
||||||
|
if len(fixture_dirs) != len(set(fixture_dirs)):
|
||||||
|
raise ImproperlyConfigured("settings.FIXTURE_DIRS contains duplicates.")
|
||||||
for app_config in apps.get_app_configs():
|
for app_config in apps.get_app_configs():
|
||||||
if self.app_label and app_config.label != self.app_label:
|
app_label = app_config.label
|
||||||
continue
|
|
||||||
app_dir = os.path.join(app_config.path, 'fixtures')
|
app_dir = os.path.join(app_config.path, 'fixtures')
|
||||||
|
if app_dir in fixture_dirs:
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
"'%s' is a default fixture directory for the '%s' app "
|
||||||
|
"and cannot be listed in settings.FIXTURE_DIRS." % (app_dir, app_label)
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.app_label and app_label != self.app_label:
|
||||||
|
continue
|
||||||
if os.path.isdir(app_dir):
|
if os.path.isdir(app_dir):
|
||||||
dirs.append(app_dir)
|
dirs.append(app_dir)
|
||||||
dirs.extend(list(settings.FIXTURE_DIRS))
|
dirs.extend(list(fixture_dirs))
|
||||||
dirs.append('')
|
dirs.append('')
|
||||||
dirs = [upath(os.path.abspath(os.path.realpath(d))) for d in dirs]
|
dirs = [upath(os.path.abspath(os.path.realpath(d))) for d in dirs]
|
||||||
return dirs
|
return dirs
|
||||||
|
|
|
@ -284,6 +284,10 @@ Management Commands
|
||||||
* The :djadminopt:`--name` option for :djadmin:`makemigrations` allows you to
|
* The :djadminopt:`--name` option for :djadmin:`makemigrations` allows you to
|
||||||
to give the migration(s) a custom name instead of a generated one.
|
to give the migration(s) a custom name instead of a generated one.
|
||||||
|
|
||||||
|
* The :djadmin:`loaddata` command now prevents repeated fixture loading. If
|
||||||
|
:setting:`FIXTURE_DIRS` contains duplicates or a default fixture directory
|
||||||
|
path (``app_name/fixtures``), an exception is raised.
|
||||||
|
|
||||||
Migrations
|
Migrations
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import re
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.serializers.base import DeserializationError
|
from django.core.serializers.base import DeserializationError
|
||||||
from django.core import management
|
from django.core import management
|
||||||
from django.core.management.base import CommandError
|
from django.core.management.base import CommandError
|
||||||
|
@ -486,6 +487,48 @@ class TestFixtures(TestCase):
|
||||||
verbosity=0,
|
verbosity=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@override_settings(FIXTURE_DIRS=[os.path.join(_cur_dir, 'fixtures_1'),
|
||||||
|
os.path.join(_cur_dir, 'fixtures_1')])
|
||||||
|
def test_fixture_dirs_with_duplicates(self):
|
||||||
|
"""
|
||||||
|
settings.FIXTURE_DIRS cannot contain duplicates in order to avoid
|
||||||
|
repeated fixture loading.
|
||||||
|
"""
|
||||||
|
self.assertRaisesMessage(
|
||||||
|
ImproperlyConfigured,
|
||||||
|
"settings.FIXTURE_DIRS contains duplicates.",
|
||||||
|
management.call_command,
|
||||||
|
'loaddata',
|
||||||
|
'absolute.json',
|
||||||
|
verbosity=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
@override_settings(FIXTURE_DIRS=[os.path.join(_cur_dir, 'fixtures')])
|
||||||
|
def test_fixture_dirs_with_default_fixture_path(self):
|
||||||
|
"""
|
||||||
|
settings.FIXTURE_DIRS cannot contain a default fixtures directory
|
||||||
|
for application (app/fixtures) in order to avoid repeated fixture loading.
|
||||||
|
"""
|
||||||
|
self.assertRaisesMessage(
|
||||||
|
ImproperlyConfigured,
|
||||||
|
"'%s' is a default fixture directory for the '%s' app "
|
||||||
|
"and cannot be listed in settings.FIXTURE_DIRS."
|
||||||
|
% (os.path.join(_cur_dir, 'fixtures'), 'fixtures_regress'),
|
||||||
|
management.call_command,
|
||||||
|
'loaddata',
|
||||||
|
'absolute.json',
|
||||||
|
verbosity=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
@override_settings(FIXTURE_DIRS=[os.path.join(_cur_dir, 'fixtures_1'),
|
||||||
|
os.path.join(_cur_dir, 'fixtures_2')])
|
||||||
|
def test_loaddata_with_valid_fixture_dirs(self):
|
||||||
|
management.call_command(
|
||||||
|
'loaddata',
|
||||||
|
'absolute.json',
|
||||||
|
verbosity=0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NaturalKeyFixtureTests(TestCase):
|
class NaturalKeyFixtureTests(TestCase):
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue