From c7e7f176c13b1070c689feb5255c07b524933e12 Mon Sep 17 00:00:00 2001
From: Jacob Walls <jacobtylerwalls@gmail.com>
Date: Sun, 2 Aug 2020 16:20:30 -0400
Subject: [PATCH] Fixed #26977 -- Made abstract models raise TypeError when
 instantiating.

---
 django/db/models/base.py        |  2 ++
 docs/releases/3.2.txt           |  2 ++
 tests/auth_tests/test_models.py | 11 +++++------
 tests/model_meta/tests.py       | 11 ++++++++++-
 4 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/django/db/models/base.py b/django/db/models/base.py
index df5b0ca137..3792ffb90e 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -409,6 +409,8 @@ class Model(metaclass=ModelBase):
         opts = self._meta
         _setattr = setattr
         _DEFERRED = DEFERRED
+        if opts.abstract:
+            raise TypeError('Abstract models cannot be instantiated.')
 
         pre_init.send(sender=cls, args=args, kwargs=kwargs)
 
diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt
index d854c7e53f..d1e21b2868 100644
--- a/docs/releases/3.2.txt
+++ b/docs/releases/3.2.txt
@@ -435,6 +435,8 @@ Miscellaneous
   in the :class:`~django.apps.AppConfig` subclass if you need to prevent this
   behavior. See :ref:`whats-new-3.2` for more details.
 
+* Instantiating an abstract model now raises ``TypeError``.
+
 .. _deprecated-features-3.2:
 
 Features deprecated in 3.2
diff --git a/tests/auth_tests/test_models.py b/tests/auth_tests/test_models.py
index 2379f68b83..5a4c5cdecd 100644
--- a/tests/auth_tests/test_models.py
+++ b/tests/auth_tests/test_models.py
@@ -6,7 +6,7 @@ from django.contrib.auth.backends import ModelBackend
 from django.contrib.auth.base_user import AbstractBaseUser
 from django.contrib.auth.hashers import get_hasher
 from django.contrib.auth.models import (
-    AbstractUser, AnonymousUser, Group, Permission, User, UserManager,
+    AnonymousUser, Group, Permission, User, UserManager,
 )
 from django.contrib.contenttypes.models import ContentType
 from django.core import mail
@@ -215,8 +215,7 @@ class AbstractBaseUserTests(SimpleTestCase):
                 self.assertEqual(username, 'iamtheΩ')  # U+03A9 GREEK CAPITAL LETTER OMEGA
 
     def test_default_email(self):
-        user = AbstractBaseUser()
-        self.assertEqual(user.get_email_field_name(), 'email')
+        self.assertEqual(AbstractBaseUser.get_email_field_name(), 'email')
 
     def test_custom_email(self):
         user = CustomEmailField()
@@ -233,8 +232,8 @@ class AbstractUserTestCase(TestCase):
             "connection": None,
             "html_message": None,
         }
-        abstract_user = AbstractUser(email='foo@bar.com')
-        abstract_user.email_user(
+        user = User(email='foo@bar.com')
+        user.email_user(
             subject="Subject here",
             message="This is a message",
             from_email="from@domain.com",
@@ -245,7 +244,7 @@ class AbstractUserTestCase(TestCase):
         self.assertEqual(message.subject, "Subject here")
         self.assertEqual(message.body, "This is a message")
         self.assertEqual(message.from_email, "from@domain.com")
-        self.assertEqual(message.to, [abstract_user.email])
+        self.assertEqual(message.to, [user.email])
 
     def test_last_login_default(self):
         user1 = User.objects.create(username='user1')
diff --git a/tests/model_meta/tests.py b/tests/model_meta/tests.py
index ad58b336bd..32bcfbc9e6 100644
--- a/tests/model_meta/tests.py
+++ b/tests/model_meta/tests.py
@@ -279,10 +279,19 @@ class ParentListTests(SimpleTestCase):
 class PropertyNamesTests(SimpleTestCase):
     def test_person(self):
         # Instance only descriptors don't appear in _property_names.
-        self.assertEqual(AbstractPerson().test_instance_only_descriptor, 1)
+        self.assertEqual(BasePerson().test_instance_only_descriptor, 1)
+        with self.assertRaisesMessage(AttributeError, 'Instance only'):
+            AbstractPerson.test_instance_only_descriptor
         self.assertEqual(AbstractPerson._meta._property_names, frozenset(['pk', 'test_property']))
 
 
 class ReturningFieldsTests(SimpleTestCase):
     def test_pk(self):
         self.assertEqual(Relation._meta.db_returning_fields, [Relation._meta.pk])
+
+
+class AbstractModelTests(SimpleTestCase):
+    def test_abstract_model_not_instantiated(self):
+        msg = 'Abstract models cannot be instantiated.'
+        with self.assertRaisesMessage(TypeError, msg):
+            AbstractPerson()