【发布时间】:2018-06-10 01:35:34
【问题描述】:
我正在尝试做一些元类恶作剧。我想要我自己的元类
从ModelBase 继承,然后我想添加额外的逻辑
扩展其__new__ 方法。不过我觉得有些东西
在我使用它的方式中,MRO/继承顺序发生了奇怪的事情。
基本情况如下:
from django.db.models import Model, ModelBase
class CustomMetaclass(ModelBase):
def __new__(cls, name, bases, attrs):
# As I am trying to extend `ModelBase`, I was expecting this
# call to `super` to give me the return value from here:
# https://github.com/django/django/blob/master/django/db/models/base.py#L300
# And that I would be able to access everyhing in `_meta` with
# `clsobj._meta`. But actually this object is
# `MyAbstractModel` and has no `_meta` property so I'm pretty
# sure `__new__` isn't being called on `ModelBase` at all at
# this point.
clsobj = super().__new__(cls, name, bases, attrs)
# Now, I want to have access to the `_meta` property setup by
# `ModelBase` so I can dispatch on the data in there. For
# example, let's do something with the field definitions.
for field in clsobj._meta.get_fields():
do_stuff_with_fields()
return clsobj
class MyAbstractModel(metaclass=CustomMetaclass):
"""This model is abstract because I only want the custom metaclass
logic to apply to those models of my choosing and I don't want to
be able to instantiate it directly. See the class definitions below.
"""
class Meta:
abstract = True
class MyModel(Model):
"""Regular model, will be derived from metaclass `ModelBase` as usual.
"""
pass
class MyCustomisedModel(MyAbstractModel):
"""This model should enjoy the logic defined by our extended `__new__` method.
"""
pass
知道为什么ModelBase 上的__new__ 没有被调用
CustomMetaClass?如何以这种方式正确扩展ModelBase?我很确定元类继承是可能的
但似乎我错过了什么......
【问题讨论】:
-
您的代码看起来不错,只是您需要在
__new__中返回clsobj。 -
是的,很好,我实际上正在这样做,但为简洁起见,我省略了它;我已将其添加到上面。但是它没有回答这个问题,因为我已经表明我需要在我的自定义
__new__方法返回任何内容之前从ModelBase中的__new__返回对象。 -
是的。您在
CustomMetaclass .__new__中的评论说明了一切。ModelBase.__new__被调用,只是访问未设置的_meta属性会破坏它,因为ModelBase.__new__returns early when there are no bases -
您可以做的就是将模型声明为基础。例如
MyAbstractModel(Model, metaclass=CustomMetaclass) -
@OluwafemiSule 在早期回归中表现出色,我确实忽略了这一点。添加
Model不会像你建议的那样工作,但是因为AppRegistry没有加载。虽然我认为我有一个解决方案,但我会尽快将其作为完整答案发布。
标签: python django inheritance metaclass method-resolution-order