diff --git a/wagtail/wagtailadmin/blocks.py b/wagtail/wagtailadmin/blocks.py index 31d597aab..d148f531a 100644 --- a/wagtail/wagtailadmin/blocks.py +++ b/wagtail/wagtailadmin/blocks.py @@ -45,10 +45,28 @@ def js_dict(d): # Top-level superclasses and helper objects # ========================================= + +class BaseBlock(type): + def __new__(mcs, name, bases, attrs): + meta_class = attrs.pop('Meta', None) + + cls = super(BaseBlock, mcs).__new__(mcs, name, bases, attrs) + + base_meta_class = getattr(cls, '_meta_class', None) + bases = tuple(cls for cls in [meta_class, base_meta_class] if cls) or (object, ) + cls._meta_class = type(name + 'Meta', bases, {}) + + return cls + + @deconstructible -class Block(object): +class Block(six.with_metaclass(BaseBlock, object)): + name = '' creation_counter = 0 - icon = "streamfield-block-placeholder" + + class Meta: + label = None + icon = "streamfield-block-placeholder" """ Setting a 'dependencies' list serves as a shortcut for the common case where a complex block type @@ -81,11 +99,10 @@ class Block(object): return mark_safe('\n'.join(declarations)) def __init__(self, **kwargs): - if 'default' in kwargs: - self.default = kwargs['default'] # if not specified, leave as the class-level default - if 'icon' in kwargs: - self.icon = kwargs['icon'] # if not specified, leave as the class-level default - self.label = kwargs.get('label', None) + self.meta = self._meta_class() + + for attr, value in kwargs.items(): + setattr(self.meta, attr, value) # Increase the creation counter, and save our local copy. self.creation_counter = Block.creation_counter @@ -95,9 +112,8 @@ class Block(object): def set_name(self, name): self.name = name - # if we don't have a label already, generate one from name - if self.label is None: - self.label = capfirst(name.replace('_', ' ')) + def get_label(self): + return self.meta.label or self.name @property def media(self): @@ -156,7 +172,7 @@ class Block(object): (new list items, for example). This will have a prefix of '__PREFIX__' (to be dynamically replaced with a real prefix when it's inserted into the page) and a value equal to the block's default value. """ - return self.bind(self.default, '__PREFIX__') + return self.bind(self.meta.default, '__PREFIX__') def clean(self, value): """ @@ -194,7 +210,7 @@ class Block(object): use a template if a 'template' property is specified on the block, and fall back on render_basic otherwise. """ - template = getattr(self, 'template', None) + template = getattr(self.meta, 'template', None) if template: return render_to_string(template, {'self': value}) else: @@ -227,18 +243,19 @@ class BoundBlock(object): # ========== class TextInputBlock(Block): - default = '' + class Meta: + default = '' def render_form(self, value, prefix='', error=None): - if self.label: + if self.get_label(): return format_html( """ """, - prefix=prefix, label=self.label, value=value + prefix=prefix, label=self.get_label(), value=value ) else: return format_html( """""", - prefix=prefix, label=self.label, value=value + prefix=prefix, label=self.get_label(), value=value ) def value_from_datadict(self, data, files, prefix): @@ -255,7 +272,8 @@ class TextInputBlock(Block): # would affect anything you're doing in migrations) class FieldBlock(Block): - default = None + class Meta: + default = None def __init__(self, field, **kwargs): super(FieldBlock, self).__init__(**kwargs) @@ -264,10 +282,17 @@ class FieldBlock(Block): def render_form(self, value, prefix='', error=None): widget = self.field.widget - if self.label: + widget_html = widget.render(prefix, value, {'id': prefix}) + + #if error: + # error_html = str(ErrorList(error.error_list)) + #else: + # error_html = '' + + if self.get_label(): label_html = format_html( """ """, - label_id=widget.id_for_label(prefix), label=self.label + label_id=widget.id_for_label(prefix), label=self.get_label() ) else: label_html = '' @@ -311,7 +336,8 @@ class RichTextBlock(FieldBlock): # ======= class ChooserBlock(Block): - default = None + class Meta: + default = None @property def media(self): @@ -321,10 +347,10 @@ class ChooserBlock(Block): return "Chooser('%s')" % self.definition_prefix def render_form(self, value, prefix='', error=None): - if self.label: + if self.get_label(): return format_html( """ """, - label=self.label, prefix=prefix + label=self.get_label(), prefix=prefix ) else: return format_html( @@ -341,8 +367,9 @@ class ChooserBlock(Block): # =========== class BaseStructBlock(Block): - default = {} - template = "wagtailadmin/blocks/struct.html" + class Meta: + default = {} + template = "wagtailadmin/blocks/struct.html" def __init__(self, local_blocks=None, **kwargs): super(BaseStructBlock, self).__init__(**kwargs) @@ -374,7 +401,7 @@ class BaseStructBlock(Block): def render_form(self, value, prefix='', error=None): child_renderings = [ - block.render_form(value.get(name, block.default), prefix="%s-%s" % (prefix, name), + block.render_form(value.get(name, block.meta.default), prefix="%s-%s" % (prefix, name), error=error.params.get(name) if error else None) for name, block in self.child_blocks.items() ] @@ -386,8 +413,8 @@ class BaseStructBlock(Block): # Can these be rendered with a template? - if self.label: - return format_html('