Django: form validation: accepting multiple values ​​for one field

I am looking to create a form field that takes several values ​​for a given field, validate them and save them as a list.

For example, you can run the following curl command and post several POST parameters called "email"

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

In my opinion, I can do the following to get a list of emails directly from POST data.

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

However, I would like to use form validation to clear all emails specified in the POST data.

Ideally, I would like to run form.is_valid () and then access the cleaned_data ['email'] key in the form will return a list of valid email addresses.

I studied the use of MultipleChoice fields and similar fields (because they accept multiple inputs with the same name), but these fields require you to predefine the selection. I also considered using forms, but they seem too complicated for what I'm trying to do in this case.

Does anyone know of any fields that behave this way? Thank you for reading.

+4
source share
1 answer

I'm looking for something similar, and I found this: 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() 

This is not entirely satisfactory: for example, for a list of emails, if only one message is invalid, the entire field is invalid.

You can probably rewrite the pure method so that it returns only valid "base_fields" instead of throwing a ValidationError at all.

+2
source

Source: https://habr.com/ru/post/1437477/


All Articles