Opened 13 months ago
Last modified 13 months ago
#35827 new New feature
Model subclass with __init_subclass__ doesn't get correct _meta instance
| Reported by: | Ben Beecher | Owned by: | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 5.0 | 
| Severity: | Normal | Keywords: | |
| Cc: | Carlton Gibson, Clifford Gama | Triage Stage: | Someday/Maybe | 
| Has patch: | yes | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description (last modified by )
When defining and using a model mixin like so:
class ModelMixin(Model):
    class Meta:
        abstract = True
    
    def __init_subclass__(cls) -> None:
        super().__init_subclass__()
        breakpoint()
        cls._my_setup_func()
class TestModel(ModelMixin):
    name = models.CharField(max_length=100)
The init_subclass call will be first called when the class is created here:
https://github.com/django/django/blob/main/django/db/models/base.py#L120
However the meta is attached here: 
https://github.com/django/django/blob/main/django/db/models/base.py#L143
So during the init_subclass call you will have the superclass' meta object if you try to access it.
55 def __init_subclass__(cls) -> None: 56 super().__init_subclass__() 57 breakpoint() 58 -> cls._my_setup_func() (Pdb++) cls <class 'label.TestModel'> (Pdb++) cls._meta <Options for ModelMixin>
Change History (8)
comment:1 by , 13 months ago
| Description: | modified (diff) | 
|---|
comment:2 by , 13 months ago
| Description: | modified (diff) | 
|---|
comment:3 by , 13 months ago
| Description: | modified (diff) | 
|---|
comment:4 by , 13 months ago
| Description: | modified (diff) | 
|---|
comment:5 by , 13 months ago
| Component: | Uncategorized → Database layer (models, ORM) | 
|---|---|
| Triage Stage: | Unreviewed → Someday/Maybe | 
| Type: | Uncategorized → New feature | 
comment:6 by , 13 months ago
#27880 by replacing Options.contribute_to_class() with Options.__set_name__() allows _meta to be added when the model class is created (type.__new__() in ModelBase). If that gets added then __init_subclass__() will be supported; or rather, the correct _meta will be accessible to __init_subclass__().
comment:7 by , 13 months ago
| Cc: | added | 
|---|
comment:8 by , 13 months ago
| Cc: | added | 
|---|---|
| Has patch: | set | 
Thought I should link this new PR on #27880 as it would address this ticket and #34555
I think this can be won't-fix on the same ground as #34555.
In order to truly support
__init_subclass__for different use case we'd need someone to own the problem space and suggest an implementation change toBaseModel.__new__that is backward compatible and receives the support of the developers on the forum like any new large feature requests.