Newer
Older
from collections import OrderedDict
from django.forms.forms import DeclarativeFieldsMetaclass
from wagtail.wagtailforms.forms import BaseForm
from wagtail.wagtailforms.models import AbstractForm
from .blocks import FormFieldBlock
class MixedFieldMetaclass(DeclarativeFieldsMetaclass):
def __new__(mcs, name, bases, attrs):
display = attrs.copy()
new_class = super(MixedFieldMetaclass, mcs).__new__(mcs, name, bases, attrs)
new_class.display = display
return new_class
class StreamBaseForm(BaseForm, metaclass=MixedFieldMetaclass):
def _html_output(self, *args, **kwargs):
# Replaces the form fields with the display fields
# should only add new streamblocks and wont affect validation
fields = self.fields.copy()
self.fields = self.display
render = super()._html_output(*args, **kwargs)
self.fields = fields
return render
class BlockFieldWrapper:
"""Wraps block stream blocks so that they can be rendered as a field within a form"""
is_hidden = False
label = None
help_text = None
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def __init__(self, block):
self.block = block
def get_bound_field(self, *args, **kwargs):
return self
def css_classes(self):
return list()
@property
def errors(self):
return list()
@property
def html_name(self):
return self.block.id
def __str__(self):
return str(self.block.value)
class AbstractStreamForm(AbstractForm):
class Meta:
abstract = True
def get_form_fields(self):
form_fields = OrderedDict()
field_blocks = self.form_fields
for struct_child in field_blocks:
block = struct_child.block
struct_value = struct_child.value
if isinstance(block, FormFieldBlock):
field_name = block.get_slug(struct_value)
form_fields[field_name] = block.get_field(struct_value)
else:
form_fields[struct_child.id] = BlockFieldWrapper(struct_child)
return form_fields
def get_form_class(self):
return type('WagtailStreamForm', (StreamBaseForm,), self.get_form_fields())