Opened 4 months ago

Last modified 4 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
Pull Requests:How to create a pull request

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>

According to the ticket's flags, the next step(s) to move this issue forward are:

  • Unknown. The Someday/Maybe triage stage is used to keep track of high-level ideas or long term feature requests.

    It could be an issue that's blocked until a future version of Django (if so, Keywords will contain that version number). It could also be an enhancement request that we might consider adding someday to the framework if an excellent patch is submitted.

    If you're interested in contributing to the issue, raising your ideas on the Django Forum would be a great place to start.

Change History (8)

comment:1 by Ben Beecher, 4 months ago

Description: modified (diff)

comment:2 by Ben Beecher, 4 months ago

Description: modified (diff)

comment:3 by Ben Beecher, 4 months ago

Description: modified (diff)

comment:4 by Ben Beecher, 4 months ago

Description: modified (diff)

comment:5 by Simon Charette, 4 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, 4 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 4 months ago by Clifford Gama (previous) (diff)

comment:7 by Carlton Gibson, 4 months ago

Cc: Carlton Gibson added

comment:8 by Clifford Gama, 4 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