From 64d5ffe2b28803b09b6804cb42e4437a3f469da1 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Fri, 13 Feb 2015 22:25:46 +0000 Subject: [PATCH] Always deconstruct StreamBlock and StructBlock as basic non-subclassed instances --- wagtail/wagtailcore/blocks.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/wagtail/wagtailcore/blocks.py b/wagtail/wagtailcore/blocks.py index 296eb024f..30b19e72f 100644 --- a/wagtail/wagtailcore/blocks.py +++ b/wagtail/wagtailcore/blocks.py @@ -446,6 +446,8 @@ class BaseStructBlock(Block): template = "wagtailadmin/blocks/struct.html" def __init__(self, local_blocks=None, **kwargs): + self._constructor_kwargs = kwargs + super(BaseStructBlock, self).__init__(**kwargs) self.child_blocks = self.base_blocks.copy() # create a local (shallow) copy of base_blocks so that it can be supplemented by local_blocks @@ -540,6 +542,21 @@ class BaseStructBlock(Block): for name, val in value.items() ]) + def deconstruct(self): + """ + Always deconstruct StructBlock instances as if they were plain StructBlocks with all of the + field definitions passed to the constructor - even if in reality this is a subclass of StructBlock + with the fields defined declaratively, or some combination of the two. + + This ensures that the field definitions get frozen into migrations, rather than leaving a reference + to a custom subclass in the user's models.py that may or may not stick around. + """ + path = 'wagtail.wagtailcore.blocks.StructBlock' + args = [self.child_blocks.items()] + kwargs = self._constructor_kwargs + return (path, args, kwargs) + + @python_2_unicode_compatible # provide equivalent __unicode__ and __str__ methods on Py2 class StructValue(collections.OrderedDict): def __init__(self, block, *args): @@ -745,6 +762,8 @@ class BaseStreamBlock(Block): return StreamValue(self, []) def __init__(self, local_blocks=None, **kwargs): + self._constructor_kwargs = kwargs + super(BaseStreamBlock, self).__init__(**kwargs) self.child_blocks = self.base_blocks.copy() # create a local (shallow) copy of base_blocks so that it can be supplemented by local_blocks @@ -906,6 +925,20 @@ class BaseStreamBlock(Block): [(child, child.block_type) for child in value] ) + def deconstruct(self): + """ + Always deconstruct StreamBlock instances as if they were plain StreamBlocks with all of the + field definitions passed to the constructor - even if in reality this is a subclass of StreamBlock + with the fields defined declaratively, or some combination of the two. + + This ensures that the field definitions get frozen into migrations, rather than leaving a reference + to a custom subclass in the user's models.py that may or may not stick around. + """ + path = 'wagtail.wagtailcore.blocks.StreamBlock' + args = [self.child_blocks.items()] + kwargs = self._constructor_kwargs + return (path, args, kwargs) + class StreamBlock(six.with_metaclass(DeclarativeSubBlocksMetaclass, BaseStreamBlock)): pass