在Wagtail Form Builder中,有没有一种方法可以创建比“选择”更多的选项

时间:2019-03-24 18:36:50

标签: django python-3.x forms wagtail

我正在编写一个新的网页,该网页也应作为某些事件的注册平台。我想在多选字段的options['prices']边添加options['choices']

现在有一个供选择的字段,其中choiceas用逗号分隔,我希望另一个字段根据选择(浮动,尽管可以在其他地方进行处理)输入默认值与默认值的差价,例如"1, 2.5, -1, 0"。表格末尾应计算默认值和所有可能的选择之和。

我尝试修改wagtail.contrib.contrib.forms.FormBuilder.create_multiselect_field失败。有没有办法添加这种功能,基本上只是一个附加的选项输入?

1 个答案:

答案 0 :(得分:1)

最后找到了一种方法,并再次学到了很多东西。

是的,这是可能的,甚至是相当简单的方法。我的表单使用的是AbstractEmailForm,我不得不重写以下方法和变量:

MyForm类(AbstractEmailForm):

form_builder = CustomFormBuilder

def get_submission_class(self):
    return CustomFormSubmission

def process_form_submission(self, form):
    #This function processed input data form.cleaned_data dict when user is submitting the form
    #Fields are defined in CustomFormSubmission

    total_price = self.default_price
    form_fields = self.get_form_fields()

    for i in form_fields:
        if i.prices: #if form creator has defined varying prices for choices
            #creates dict {key=choice, value=price} for every form field
            price_dict = dict(zip(
                [x.strip() for x in i.choices.split(',')],
                [Decimal(x.strip()) for x in i.prices.split(',')], #field type is DecimalField, float is not applicable
            ))

            total_price += price_dict[form.cleaned_data[i.label.lower()]]

    return self.get_submission_class().objects.create(
        form_data=json.dumps(form.cleaned_data, cls=DjangoJSONEncoder),
        page=self,
        price=total_price,
    )

def get_data_fields(self):
    """
    Returns a list of tuples with (field_name, field_label).
    """

    data_fields = [
        ('submit_time', _('Submission date')),
        ('price', _('Total Price')),
    ]
    data_fields += [
        (field.clean_name, field.label)
        for field in self.get_form_fields()
    ]

    return data_fields

此外,我还必须为表单编辑器字段选择价格。这可以通过重写AbstractFormField类来实现。您必须在要应用价格选项的地方覆盖每个create__field()函数。例如下面的create_radio_field:

FormField(AbstractFormField)类:

prices = models.TextField(
    verbose_name=_('prices'),
    blank=True,
    help_text=_('Comma separated list of price changes.')
)

panels = [
    FieldPanel('label'),
    FieldPanel('help_text'),
    FieldPanel('required'),
    FieldPanel('field_type', classname="formbuilder-type"),
    FieldPanel('choices', classname="formbuilder-choices"),
    FieldPanel('prices'),
    FieldPanel('default_value', classname="formbuilder-default"),
]

def create_radio_field(self, field, options):
    options['choices'] = [(x.strip(), x.strip()) for x in field.choices.split(',')]
    options['prices'] = [x.strip() for x in field.prices.split(',')]
    return django.forms.ChoiceField(
        widget=django.forms.RadioSelect, 
        **options
    )
enter code here
#remember to create CustomFormBuilder(FormBuilder) if you have custom fields, ex. Generic IP-address:

class CustomFormBuilder(FormBuilder):
    def create_ipaddress_field(self, field, options):
        return forms.GenericIPAddressField(
            **options
    )

要保存此值,请使用CustomFormSubmission(AbstractFormSubmission)定义要在数据库中创建的字段

price = models.DecimalField(
    max_digits=16,
    decimal_places=2,
    default=0,
)

def get_data(self):
    """
    Returns dict with form data.
    """
    form_data = json.loads(self.form_data)
    form_data.update({
        'submit_time': self.submit_time,
        'price': self.price,
    })

    return form_data

货币保存在Django模型中。DecimalField仅需要2个小数。浮点数在取整时可能会有奇怪的行为。

如果您有任何疑问,我将很乐意为您打开更多代码!