diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py
index 05cf769489..aae69afc9b 100644
--- a/django/core/management/commands/loaddata.py
+++ b/django/core/management/commands/loaddata.py
@@ -9,6 +9,7 @@ import zipfile
 from django.apps import apps
 from django.conf import settings
 from django.core import serializers
+from django.core.exceptions import ImproperlyConfigured
 from django.core.management.base import BaseCommand, CommandError
 from django.core.management.color import no_style
 from django.db import (connections, router, transaction, DEFAULT_DB_ALIAS,
@@ -238,13 +239,23 @@ class Command(BaseCommand):
         current directory.
         """
         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():
-            if self.app_label and app_config.label != self.app_label:
-                continue
+            app_label = app_config.label
             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):
                 dirs.append(app_dir)
-        dirs.extend(list(settings.FIXTURE_DIRS))
+        dirs.extend(list(fixture_dirs))
         dirs.append('')
         dirs = [upath(os.path.abspath(os.path.realpath(d))) for d in dirs]
         return dirs
diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt
index d02672be9a..f84294d459 100644
--- a/docs/releases/1.8.txt
+++ b/docs/releases/1.8.txt
@@ -284,6 +284,10 @@ Management Commands
 * The :djadminopt:`--name` option for :djadmin:`makemigrations` allows you to
   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
 ^^^^^^^^^^
 
diff --git a/tests/fixtures_regress/tests.py b/tests/fixtures_regress/tests.py
index 0ec48bc5e9..171ef30fec 100644
--- a/tests/fixtures_regress/tests.py
+++ b/tests/fixtures_regress/tests.py
@@ -8,6 +8,7 @@ import re
 import warnings
 
 from django.core import serializers
+from django.core.exceptions import ImproperlyConfigured
 from django.core.serializers.base import DeserializationError
 from django.core import management
 from django.core.management.base import CommandError
@@ -486,6 +487,48 @@ class TestFixtures(TestCase):
             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):