3

フォームでは、複数のフィールドを持つ MultiWidget で MultiValueField (MVF) を使用しています。MVF のフィールドの 1 つに検証エラーがある場合、個々のサブフィールドではなく 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 の最初のフィールドを参照し、2 番目のエラーは 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 に答える