add IPAddressField, update docs

This commit is contained in:
Aider Ibragimov 2015-02-28 10:11:38 +03:00
parent aa7ed316d8
commit 4d5eee04a0
3 changed files with 63 additions and 2 deletions

View File

@ -188,6 +188,17 @@ A field that ensures the input is a valid UUID string. The `to_internal_value` m
"de305d54-75b4-431b-adb2-eb6b9e546013" "de305d54-75b4-431b-adb2-eb6b9e546013"
## IPAddressField
A field that ensures the input is a valid IPv4 or IPv6 string.
Corresponds to `django.forms.fields.IPAddressField` and `django.forms.fields.GenericIPAddressField`.
**Signature**: `IPAddressField(protocol='both', unpack_ipv4=False, **options)`
- `protocol` Limits valid inputs to the specified protocol. Accepted values are 'both' (default), 'IPv4' or 'IPv6'. Matching is case insensitive.
- `unpack_ipv4` Unpacks IPv4 mapped addresses like ::ffff:192.0.2.1. If this option is enabled that address would be unpacked to 192.0.2.1. Default is disabled. Can only be used when protocol is set to 'both'.
--- ---
# Numeric fields # Numeric fields
@ -524,7 +535,7 @@ As an example, let's create a field that can be used represent the class name of
# We pass the object instance onto `to_representation`, # We pass the object instance onto `to_representation`,
# not just the field attribute. # not just the field attribute.
return obj return obj
def to_representation(self, obj): def to_representation(self, obj):
""" """
Serialize the object's class name. Serialize the object's class name.

View File

@ -2,12 +2,13 @@ from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.exceptions import ValidationError as DjangoValidationError from django.core.exceptions import ValidationError as DjangoValidationError
from django.core.validators import RegexValidator from django.core.validators import RegexValidator, ip_address_validators
from django.forms import ImageField as DjangoImageField from django.forms import ImageField as DjangoImageField
from django.utils import six, timezone from django.utils import six, timezone
from django.utils.dateparse import parse_date, parse_datetime, parse_time from django.utils.dateparse import parse_date, parse_datetime, parse_time
from django.utils.encoding import is_protected_type, smart_text from django.utils.encoding import is_protected_type, smart_text
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.ipv6 import clean_ipv6_address
from rest_framework import ISO_8601 from rest_framework import ISO_8601
from rest_framework.compat import ( from rest_framework.compat import (
EmailValidator, MinValueValidator, MaxValueValidator, EmailValidator, MinValueValidator, MaxValueValidator,
@ -650,6 +651,34 @@ class UUIDField(Field):
return str(value) return str(value)
class IPAddressField(CharField):
"""Support both IPAddressField and GenericIPAddressField"""
default_error_messages = {
'invalid': _('Enter a valid IPv4 or IPv6 address.'),
}
def __init__(self, protocol='both', unpack_ipv4=False, **kwargs):
self.protocol = protocol
self.unpack_ipv4 = unpack_ipv4
super(IPAddressField, self).__init__(**kwargs)
validators, error_message = ip_address_validators(protocol, unpack_ipv4)
self.validators.extend(validators)
def to_internal_value(self, data):
if data == '' and self.allow_blank:
return ''
data = data.strip()
if data and ':' in data:
try:
return clean_ipv6_address(data, self.unpack_ipv4)
except DjangoValidationError:
self.fail('invalid', value=data)
return data
# Number types... # Number types...
class IntegerField(Field): class IntegerField(Field):

View File

@ -485,6 +485,27 @@ class TestUUIDField(FieldValues):
field = serializers.UUIDField() field = serializers.UUIDField()
class TestIPAddressField(FieldValues):
"""
Valid and invalid values for `IPAddressField`
"""
valid_inputs = {
'127.0.0.1': '127.0.0.1',
'192.168.33.255': '192.168.33.255',
'2001:0db8:85a3:0042:1000:8a2e:0370:7334': '2001:db8:85a3:42:1000:8a2e:370:7334',
'2001:cdba:0:0:0:0:3257:9652': '2001:cdba::3257:9652',
'2001:cdba::3257:9652': '2001:cdba::3257:9652'
}
invalid_inputs = {
'127001': ['Enter a valid IPv4 or IPv6 address.'],
'127.122.111.2231': ['Enter a valid IPv4 or IPv6 address.'],
'2001:::9652': ['Enter a valid IPv4 or IPv6 address.'],
'2001:0db8:85a3:0042:1000:8a2e:0370:73341': ['Enter a valid IPv4 or IPv6 address.'],
}
outputs = {}
field = serializers.IPAddressField()
# Number types... # Number types...
class TestIntegerField(FieldValues): class TestIntegerField(FieldValues):