diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 7a4c15c3c1..6df1e34288 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -880,6 +880,11 @@ class IPAddressField(Field): def validate(self, field_data, all_data): validators.isValidIPAddress4(field_data, None) + def formfield(self, **kwargs): + defaults = {'form_class': forms.IPAddressField} + defaults.update(kwargs) + return super(IPAddressField, self).formfield(**defaults) + class NullBooleanField(Field): empty_strings_allowed = False def __init__(self, *args, **kwargs): diff --git a/django/newforms/fields.py b/django/newforms/fields.py index 8fb1d4f392..a39987e1b5 100644 --- a/django/newforms/fields.py +++ b/django/newforms/fields.py @@ -26,7 +26,7 @@ __all__ = ( 'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField', 'BooleanField', 'ChoiceField', 'NullBooleanField', 'MultipleChoiceField', 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', - 'SplitDateTimeField', + 'SplitDateTimeField', 'IPAddressField', ) # These values, if given to to_python(), will trigger the self.required check. @@ -635,3 +635,11 @@ class SplitDateTimeField(MultiValueField): raise ValidationError(ugettext(u'Enter a valid time.')) return datetime.datetime.combine(*data_list) return None + +ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') + +class IPAddressField(RegexField): + def __init__(self, *args, **kwargs): + RegexField.__init__(self, ipv4_re, + error_message=ugettext(u'Enter a valid IPv4 address.'), + *args, **kwargs) diff --git a/docs/newforms.txt b/docs/newforms.txt index 691aee7e44..2c8f67ce32 100644 --- a/docs/newforms.txt +++ b/docs/newforms.txt @@ -1284,6 +1284,15 @@ When you use a ``FileField`` on a form, you must also remember to Takes two optional arguments for validation, ``max_value`` and ``min_value``. These control the range of values permitted in the field. +``IPAddressField`` +~~~~~~~~~~~~~~~~~~ + + * Default widget: ``TextInput`` + * Empty value: ``''`` (an empty string) + * Normalizes to: A Unicode object. + * Validates that the given value is a valid IPv4 address, using a regular + expression. + ``MultipleChoiceField`` ~~~~~~~~~~~~~~~~~~~~~~~ @@ -1710,7 +1719,7 @@ the full list of conversions: ``ForeignKey`` ``ModelChoiceField`` (see below) ``ImageField`` ``ImageField`` ``IntegerField`` ``IntegerField`` - ``IPAddressField`` ``CharField`` + ``IPAddressField`` ``IPAddressField`` ``ManyToManyField`` ``ModelMultipleChoiceField`` (see below) ``NullBooleanField`` ``CharField`` diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index a3e61c8f06..616d6e5ff5 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -3834,6 +3834,61 @@ ValidationError: [u'This field is required.'] >>> f.cleaned_data {'field1': u'some text,JP,2007-04-25 06:24:00'} + +# IPAddressField ################################################################## + +>>> f = IPAddressField() +>>> f.clean('') +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean(None) +Traceback (most recent call last): +... +ValidationError: [u'This field is required.'] +>>> f.clean('127.0.0.1') +u'127.0.0.1' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('127.0.0.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('1.2.3.4.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('256.125.1.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] + +>>> f = IPAddressField(required=False) +>>> f.clean('') +u'' +>>> f.clean(None) +u'' +>>> f.clean('127.0.0.1') +u'127.0.0.1' +>>> f.clean('foo') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('127.0.0.') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('1.2.3.4.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] +>>> f.clean('256.125.1.5') +Traceback (most recent call last): +... +ValidationError: [u'Enter a valid IPv4 address.'] + ################################# # Tests of underlying functions # #################################