3

在一个表单中,我使用了一个 MultiValueField (MVF) 和一个具有多个字段的 MultiWidget。如果在 MVF 的某个字段中存在验证错误,则会在 MVF 级别而不是在各个子字段中处理(显示)这可能导致:

* Ensure this value is greater than or equal to 1.
* Ensure this value is greater than or equal to -100.0.

Number of days: -1
...
...
Threshold: -200

其中第一个错误是指 MVF 的第一个字段,第二个错误是指 MVF 的最后一个字段。

是否可以将这些错误消息放在它们所属的字段“内部”MVF 中?(也许在 MultiWidget 的 format_output 方法中?)

4

1 回答 1

0

以下解决方案不使用 MultiValueField 而是:

  • 用表单上的几个字段动态替换原始字段__init__
  • 在表单验证期间为原始字段重建有效数据_post_clean

这是一些需要适应每种情况的测试代码:

class MyMultiField(CharField):

    def split(self, form):
        name = 'test'
        form.fields_backup[name] = form.fields[name]
        del form.fields[name]
        # here is where you define your individual fields:
        for i in range(3):
            form.fields[name + '_' + str(i)] = CharField()
            # you need to extract the initial data for these fields
            form.initial[name + '_' + str(i)] = somefunction(form.initial[name])
        form.fields['test_1'] = DecimalField() # because I only want numbers in the 2nd field

    def restore(self, form):
        # here is where you describe how to joins the individual fields:
        value = ''.join([unicode(v) for k, v in form.cleaned_data.items() if 'test_' in k])
        # extra step to validate the combined value against the original field:
        try:
            restored_data = form.cleaned_data.copy()
            restored_data["test"] = form.fields_backup["test"].clean(value)
            for k in form.cleaned_data:
                if k.startswith("test_"):
                    del restored_data[k]
            form.cleaned_data = restored_data
        except Exception, e:
            form._errors[NON_FIELD_ERRORS] = form.error_class(e)


class MyForm(Form):

    test = MyMultiField()

    def __init__(self, *args, **kwargs):
        super(ItemForm, self).__init__(*args, **kwargs)
        self.fields_backup = {}
        self.fields['data'].split(self)

    def _post_clean(self):
        self.fields_backup['data'].restore(self)
        return super(MyForm, self)._post_clean()

前:

原始表单域

之后(验证一些输入):

多场

我不确定是否可以使用这种方法进一步解耦此字段/表单代码。我对这段代码也不太满意,因为新的字段类需要从原来的类继承。

尽管如此,基本的想法是存在的,我成功地使用它来单独验证从存储在 PostgreSQL hstore 的单个模型字段中的字典构建的表单字段。

于 2013-01-19T01:03:33.087 回答