Django Meta class abstract изменяется с True на False
Я понимаю, что когда класс наследует от абстрактной модели Django, он не наследует мета-атрибут abstract = True
, что имеет смысл.
Однако в следующем примере от него ничего не унаследовано, но все же его Meta.abstract
является False
, хотя он определен как True
:
from django.db import models
from django.db.models.base import ModelBase
class MyMeta(ModelBase):
def __new__(cls, name, bases, attrs, **kwargs):
"""Check that all implemented (not abstract) classes have a foo attribute"""
Class = super().__new__(cls, name, bases, attrs, **kwargs)
if not Class.Meta.abstract:
print(Class)
print('Class.Meta.ordering:', Class.Meta.ordering) # Sanity check
print('Class.Meta.abstract:', Class.Meta.abstract)
if not hasattr(Class, 'foo'):
raise NotImplementedError('Please add a foo attribute')
return Class
class MyAbstractModel(models.Model, metaclass=MyMeta):
name = models.CharField(max_length=250)
class Meta:
abstract = True
ordering = ('-name',)
Prints:
<class 'myapp.models.base.MyAbstractModel'>
Class.Meta.ordering: -name
Class.Meta.abstract: False
Добавить поднимает (хотя он не должен поднимать, потому что это абстрактный класс):
NotImplementedError: Please add a foo attribute
Abstract - False, поскольку дочерние классы сами не становятся абстрактными классами. Вам нужно явно установить значение True. Информация об этом есть в документации. https://docs.djangoproject.com/en/4.1/topics/db/models/
You are accessing the wrong attribute, namely Class.Meta
. Since this attribute will be inherited by any child classes Django actually modifies [GitHub] it for abstract models:
if abstract: # Abstract base models can't be instantiated and don't appear in # the list of models for an app. We do the final setup for them a # little differently from normal models. attr_meta.abstract = False new_class.Meta = attr_meta return new_class
Атрибут, который Django фактически использует за кулисами (все атрибуты правильно копируются в него), это _meta
. Следовательно, если вы напишете следующее, вы получите ожидаемый результат:
if not Class._meta.abstract:
...