diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 21153dcbb8..5954cf35f4 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -1426,14 +1426,16 @@ class ForeignObject(RelatedField):
     @staticmethod
     def get_instance_value_for_fields(instance, fields):
         ret = []
+        opts = instance._meta
         for field in fields:
             # Gotcha: in some cases (like fixture loading) a model can have
             # different values in parent_ptr_id and parent's id. So, use
             # instance.pk (that is, parent_ptr_id) when asked for instance.id.
-            opts = instance._meta
             if field.primary_key:
                 possible_parent_link = opts.get_ancestor_link(field.model)
-                if not possible_parent_link or possible_parent_link.primary_key:
+                if (not possible_parent_link or
+                        possible_parent_link.primary_key or
+                        possible_parent_link.model._meta.abstract):
                     ret.append(instance.pk)
                     continue
             ret.append(getattr(instance, field.attname))
diff --git a/tests/fixtures_regress/fixtures/feature.json b/tests/fixtures_regress/fixtures/feature.json
new file mode 100644
index 0000000000..84aa2adcf4
--- /dev/null
+++ b/tests/fixtures_regress/fixtures/feature.json
@@ -0,0 +1,17 @@
+[
+{
+  "fields": {
+    "channels": [],
+    "title": "Title of this feature article"
+  },
+  "model": "fixtures_regress.article",
+  "pk": 1
+},
+{
+  "fields": {
+    "channels": []
+  },
+  "model": "fixtures_regress.feature",
+  "pk": 1
+}
+]
diff --git a/tests/fixtures_regress/models.py b/tests/fixtures_regress/models.py
index 95f9488ab7..14f8829760 100644
--- a/tests/fixtures_regress/models.py
+++ b/tests/fixtures_regress/models.py
@@ -52,7 +52,7 @@ class Child(Parent):
     data = models.CharField(max_length=10)
 
 
-# Models to regression test #7572
+# Models to regression test #7572, #20820
 class Channel(models.Model):
     name = models.CharField(max_length=255)
 
@@ -70,6 +70,17 @@ class SpecialArticle(Article):
     pass
 
 
+# Models to regression test #22421
+class CommonFeature(Article):
+
+    class Meta:
+        abstract = True
+
+
+class Feature(CommonFeature):
+    pass
+
+
 # Models to regression test #11428
 @python_2_unicode_compatible
 class Widget(models.Model):
diff --git a/tests/fixtures_regress/tests.py b/tests/fixtures_regress/tests.py
index 61fc66d928..f99bcbe378 100644
--- a/tests/fixtures_regress/tests.py
+++ b/tests/fixtures_regress/tests.py
@@ -480,6 +480,18 @@ class TestFixtures(TestCase):
             verbosity=0,
         )
 
+    def test_ticket_22421(self):
+        """
+        Regression for ticket #22421 -- loaddata on a model that inherits from
+        a grand-parent model with a M2M but via an abstract parent shouldn't
+        blow up.
+        """
+        management.call_command(
+            'loaddata',
+            'feature.json',
+            verbosity=0,
+        )
+
 
 class NaturalKeyFixtureTests(TestCase):