Opened 2 months ago

Last modified 2 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 Ben Beecher)

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 Ben Beecher, 2 months ago

Description: modified (diff)

comment:2 by Ben Beecher, 2 months ago

Description: modified (diff)

comment:3 by Ben Beecher, 2 months ago

Description: modified (diff)

comment:4 by Ben Beecher, 2 months ago

Description: modified (diff)

comment:5 by Simon Charette, 2 months ago

Component: UncategorizedDatabase layer (models, ORM)
Triage Stage: UnreviewedSomeday/Maybe
Type: UncategorizedNew feature

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 to BaseModel.__new__ that is backward compatible and receives the support of the developers on the forum like any new large feature requests.

comment:6 by Clifford Gama, 2 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__().

Last edited 2 months ago by Clifford Gama (previous) (diff)

comment:7 by Carlton Gibson, 2 months ago

Cc: Carlton Gibson added

comment:8 by Clifford Gama, 2 months ago

Cc: Clifford Gama added
Has patch: set

Thought I should link this new PR on #27880 as it would address this ticket and #34555

Note: See TracTickets for help on using tickets.
Back to Top