Hi Stackoverflow社区
我一直在试图理解Django(和Wagtail的溪流场)是如何在引擎盖下工作的。这样做,我学会了元类,并相信掌握了原理。也就是说,对于我来说,SIX是如何执行with_元类函数的仍然有点模糊。下面是代码后面跟着一个特定的问题:
模型.py
class BlogPage(Page):
blogElement = StreamField([
('heading', blocks.CharBlock(classname="full title")),
('paragraph', blocks.TextBlock()),
('picture', ImageChooserBlock()),
], default=[])
wagtailcore>;字段.py
^{pr2}$wagtailcore>;街区>;溪流_块.py
class StreamBlock(six.with_metaclass(DeclarativeSubBlocksMetaclass, BaseStreamBlock)):
pass
6.py
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# 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.
class metaclass(meta):
def __new__(cls, name, this_bases, d):
return meta(name, bases, d)
return type.__new__(metaclass, 'temporary_class', (), {})
问题
(1)描述建议我们生成一个临时的虚拟元类,用实际的元类替换它自己。 (2) 这是怎么回事? (3) 我们如何通过with_元类函数对元类生成进行排序? (4) 那么BaseStreamBlock从何而来?在
让我困惑的是我们定义
[1] class metaclass(meta):
但只能通过以下方式调用:
[2] return type.__new__(metaclass, 'temporary_class', (), {})
在[2]中,我们实例化了我们在[1]中定义的类元类。该类的实例包含DeclarativeSubBlockMetaclass作为类型,而“temporary_class”作为名称,没有基或属性。在
在[1]中,我们定义了元类类,它似乎在做实际的元类工作。这里我们开发了一个类生成器,它基于基和名称生成DeclarativeSubBlockMetaclass(作为meta传递)类型的类。在
但是,由于对[1]的唯一调用来自[2],所以我们似乎要做的就是实例化类型为DeclarativeSubBlockMetaclass的“temporary\u class”,而没有任何基或属性。在
我们如何用描述(1)中描述的实际元类替换这个临时的伪元类?在
我试着去咨询六号医院的医生,但是没有找到任何能解决我困惑的东西。在
任何建议都将不胜感激。在
非常感谢 Z
仅供参考:
我包括了在六、用元类以上电话:
声明子块类
class DeclarativeSubBlocksMetaclass(BaseBlock):
"""
Metaclass that collects sub-blocks declared on the base classes.
(cheerfully stolen from https://github.com/django/django/blob/master/django/forms/forms.py)
"""
def __new__(mcs, name, bases, attrs):
# Collect sub-blocks declared on the current class.
# These are available on the class as `declared_blocks`
current_blocks = []
for key, value in list(attrs.items()):
if isinstance(value, Block):
current_blocks.append((key, value))
value.set_name(key)
attrs.pop(key)
current_blocks.sort(key=lambda x: x[1].creation_counter)
attrs['declared_blocks'] = collections.OrderedDict(current_blocks)
new_class = (super(DeclarativeSubBlocksMetaclass, mcs).__new__(mcs, name, bases, attrs))
# Walk through the MRO, collecting all inherited sub-blocks, to make
# the combined `base_blocks`.
base_blocks = collections.OrderedDict()
for base in reversed(new_class.__mro__):
# Collect sub-blocks from base class.
if hasattr(base, 'declared_blocks'):
base_blocks.update(base.declared_blocks)
# Field shadowing.
for attr, value in base.__dict__.items():
if value is None and attr in base_blocks:
base_blocks.pop(attr)
new_class.base_blocks = base_blocks
return new_class
BaseStreamBlock
class BaseStreamBlock(Block):
def __init__(self, local_blocks=None, **kwargs):
self._constructor_kwargs = kwargs
super(BaseStreamBlock, self).__init__(**kwargs)
# create a local (shallow) copy of base_blocks so that it can be supplemented by local_blocks
self.child_blocks = self.base_blocks.copy()
if local_blocks:
for name, block in local_blocks:
block.set_name(name)
self.child_blocks[name] = block
self.dependencies = self.child_blocks.values()
好吧-我想我已经想好了。问题的关键在于
with_元类函数的:
^{pr2}$下面是我认为在sudo代码中它是如何工作的:
(7)中解释的步骤就是解释所说的。实际上,SIX所做的就是按照规定的步骤创建一个虚拟元类,它称之为临时的_类。由于DeclarativeSubBlocksMetaClass也是一个元类,因此它使用BaseStreamBlock基来生成一个新类。在
我希望这有道理。在
Z
相关问题 更多 >
编程相关推荐