Fix for typeclass app_label, and admin fix. Resolves #2112.

This commit is contained in:
Griatch 2020-06-26 21:17:07 +02:00
parent e8b99175ad
commit 5e6c52e2e6
2 changed files with 108 additions and 13 deletions

View file

@ -104,18 +104,24 @@ class TypeclassBase(SharedMemoryModelBase):
attrs["typename"] = name
attrs["path"] = "%s.%s" % (attrs["__module__"], name)
# typeclass proxy setup
app_label = None
# first check explicit __applabel__ on the typeclass
if "__applabel__" not in attrs:
# find the app-label in one of the bases, usually the dbmodel
def _get_dbmodel(bases):
"""Recursively get the dbmodel"""
if not hasattr(bases, "__iter__"):
bases = [bases]
for base in bases:
try:
attrs["__applabel__"] = base.__applabel__
except AttributeError:
pass
else:
break
if base._meta.proxy or base._meta.abstract:
for kls in base._meta.parents:
return _get_dbmodel(kls)
return base
dbmodel = _get_dbmodel(bases)
# typeclass proxy setup
# first check explicit __applabel__ on the typeclass, then figure
# it out from the dbmodel
if dbmodel and "__applabel__" not in attrs:
# find the app-label in one of the bases, usually the dbmodel
attrs["__applabel__"] = dbmodel._meta.app_label
if "Meta" not in attrs:
class Meta:
@ -127,9 +133,20 @@ class TypeclassBase(SharedMemoryModelBase):
new_class = ModelBase.__new__(cls, name, bases, attrs)
# django doesn't support inheriting proxy models so we hack support for
# it here by injecting `proxy_for_model` to the actual dbmodel.
# Unfortunately we cannot also set the correct model_name, because this
# would block multiple-inheritance of typeclasses (Django doesn't allow
# multiple bases of the same model).
if dbmodel:
new_class._meta.proxy_for_model = dbmodel
# Maybe Django will eventually handle this in the future:
# new_class._meta.model_name = dbmodel._meta.model_name
# attach signals
signals.post_save.connect(call_at_first_save, sender=new_class)
signals.pre_delete.connect(remove_attributes_on_delete, sender=new_class)
signals.pre_delete.connect(
remove_attributes_on_delete, sender=new_class)
return new_class