diff --git a/django/db/models/base.py b/django/db/models/base.py index adae730a02..bba11c9000 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -62,19 +62,9 @@ class ModelBase(type): def __new__(cls, name, bases, attrs): super_new = super(ModelBase, cls).__new__ - # six.with_metaclass() inserts an extra class called 'NewBase' in the - # inheritance tree: Model -> NewBase -> object. But the initialization - # should be executed only once for a given model class. - - # attrs will never be empty for classes declared in the standard way - # (ie. with the `class` keyword). This is quite robust. - if name == 'NewBase' and attrs == {}: - return super_new(cls, name, bases, attrs) - # Also ensure initialization is only performed for subclasses of Model # (excluding Model class itself). - parents = [b for b in bases if isinstance(b, ModelBase) and - not (b.__name__ == 'NewBase' and b.__mro__ == (b, object))] + parents = [b for b in bases if isinstance(b, ModelBase)] if not parents: return super_new(cls, name, bases, attrs) diff --git a/django/utils/six.py b/django/utils/six.py index dd171aa42f..bf94a83000 100644 --- a/django/utils/six.py +++ b/django/utils/six.py @@ -628,7 +628,21 @@ _add_doc(reraise, """Reraise an exception.""") def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) + # This requires a bit of explanation: the basic idea is to make a + # dummy metaclass for one level of class instantiation that replaces + # itself with the actual metaclass. Because of internal type checks + # we also need to make sure that we downgrade the custom metaclass + # for one level to something closer to type (that's why __call__ and + # __init__ comes back from type etc.). + class metaclass(meta): + __call__ = type.__call__ + __init__ = type.__init__ + def __new__(cls, name, this_bases, d): + if this_bases is None: + return type.__new__(cls, name, (), d) + return meta(name, bases, d) + return metaclass('temporary_class', None, {}) + def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass."""