From a5bec48ab441feda0802d8e7e4ede8dcc51aa59e Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 11 May 2023 11:39:31 +0100 Subject: [PATCH] allows Fields to be added to Models in __init_subclass__ without affecting existing ModelBase.__new__ API --- django/db/models/base.py | 5 +++++ tests/model_inheritance/tests.py | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/django/db/models/base.py b/django/db/models/base.py index 344508e0e2..d8a344e99f 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -118,6 +118,11 @@ class ModelBase(type): else: new_attrs[obj_name] = obj new_class = super_new(cls, name, bases, new_attrs, **kwargs) + # update contributable_attrs with any such attributes added to new_class - these came from __init_subclass__ + for obj_name, obj in dict(vars(new_class)).items(): + if _has_contribute_to_class(obj): + contributable_attrs[obj_name] = obj + delattr(new_class, obj_name) abstract = getattr(attr_meta, "abstract", False) meta = attr_meta or getattr(new_class, "Meta", None) diff --git a/tests/model_inheritance/tests.py b/tests/model_inheritance/tests.py index 4542e6c3cc..b644bde8cc 100644 --- a/tests/model_inheritance/tests.py +++ b/tests/model_inheritance/tests.py @@ -249,6 +249,24 @@ class ModelInheritanceTests(TestCase): self.assertEqual(saved_kwargs, kwargs) + @isolate_apps("model_inheritance") + def test_fields_can_be_added_in_init_subclass(self): + class BaseBookModel(models.Model): + class Meta: + abstract = True + + def __init_subclass__(cls, author_model_cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.author = models.ForeignKey(author_model_cls, on_delete = models.CASCADE) + + class Author(models.Model): + name = models.CharField(max_length = 256, unique = True) + + class Book(BaseBookModel, author_model_cls = Author): + pass + + self.assertIsInstance(Book._meta.get_field('author'), models.ForeignKey) + @isolate_apps("model_inheritance") def test_set_name(self): class ClassAttr: