5

特定のフィールドに複数の値を取り、それらを検証し、リストとして保存するフォーム フィールドを作成しようとしています。

たとえば、次の curl コマンドを実行して、「email」という名前のいくつかの POST パラメーターを投稿できます。

curl -X POST -d email=test@example.com -d email=test2@example.com http://url/here/

私の見解では、以下を実行して、POST データから直接電子メールのリストを取得できます。

email = request.POST.getlist('email')

ただし、フォーム検証を利用して、POST データで指定されたすべての電子メールをクリーンアップしたいと考えています。

理想的には、form.is_valid() を実行してから、フォームのcleaned_data['email'] キーにアクセスすると、有効な電子メール アドレスのリストが返されます。

MultipleChoice フィールドや同様のフィールド (同じ名前の複数の入力を受け入れるため) の使用を検討しましたが、これらのフィールドでは事前に選択肢を定義する必要があります。フォームセットの使用も検討しましたが、この場合、私がやろうとしていることは複雑すぎるようです。

このように動作するフィールドを知っている人はいますか? 読んでくれてありがとう。

4

3 に答える 3

2

私は似たようなものを探していて、これを見つけました: http://djangosnippets.org/snippets/497/

from django import newforms as forms

class SeparatedValuesField(forms.Field):
    """
    A Django newforms field which takes another newforms field during
    initialization and validates every item in a separated list with
    this field class. Please use it like this::

        from django.newforms import EmailField
        emails = SeparatedValuesField(EmailField)

    You would be able to enter a string like 'john@doe.com,guido@python.org'
    because every email address would be validated when clean() is executed.
    This of course also applies to any other Field class.

    You can define the sepator (default: ',') during initialization with the
    ``separator`` parameter like this::

        from django.newforms import EmailField
        emails = SeparatedValuesField(EmailField, separator='###')

    If validation succeeds it returns the original data, though the already
    splitted value list can be accessed with the get_list() method.

    >>> f = SeparatedValuesField(forms.EmailField)
    >>> f.clean('foo@bar.com,bar@foo.com')
    'foo@bar.com,bar@foo.com'
    >>> f.get_list()
    ['foo@bar.com', 'bar@foo.com']
    >>> f.clean('foobar,foo@bar.com,bar@foo.com')
    Traceback (most recent call last):
        ...
    ValidationError: <unprintable ValidationError object>
    >>> u = SeparatedValuesField(forms.URLField)
    >>> u.clean('http://foo.bar.com,http://foobar.com')
    'http://foo.bar.com,http://foobar.com'
    >>> u.clean('http:foo.bar.com')
    Traceback (most recent call last):
        ...
    ValidationError: <unprintable ValidationError object>
    >>> f = SeparatedValuesField(forms.EmailField, separator='###')
    >>> f.clean('foo@bar.com###bar@foo.com')
    'foo@bar.com###bar@foo.com'
    >>> f.clean('foobar###foo@bar.com###bar@foo.com')
    Traceback (most recent call last):
        ...
    ValidationError: <unprintable ValidationError object>

    """
    def __init__(self, base_field=None, separator=',', *args, **kwargs):
        super(SeparatedValuesField, self).__init__(*args, **kwargs)
        self.base_field = base_field
        self.separator = separator

    def clean(self, data):
        if not data:
            raise forms.ValidationError('Enter at least one value.')
        self.value_list = data.split(self.separator)
        if self.base_field is not None:
            base_field = self.base_field()
            for value in self.value_list:
                base_field.clean(value)
        return data

    def get_list(self):
        return self.value_list

def _test():
    import doctest
    doctest.testmod()

if __name__ == "__main__":
    _test()

ただし、完全に満足できるわけではありません。たとえば、電子メールのリストの場合、1 つの電子メールのみが無効な場合、フィールド全体が無効になります。

ValidationError をまったくスローするのではなく、有効な「base_fields」のみを返すように clean メソッドを書き直すことができます。

于 2013-05-02T14:55:30.477 に答える