Django

Code

Ticket #811: ipv6.diff

File ipv6.diff, 13.9 kB (added by Johann Queuniet <johann.queuniet@gmail.com>, 1 year ago)

IPv4/IPv6 field with doc, tests and integration with new/oldforms

  • django/oldforms/__init__.py

    old new  
    933933 
    934934    def isValidIPAddress(self, field_data, all_data): 
    935935        try: 
    936             validators.isValidIPAddress4(field_data, all_data) 
     936            validators.isValidIP4Address(field_data, all_data) 
    937937        except validators.ValidationError, e: 
    938938            raise validators.CriticalValidationError, e.messages 
    939939 
     
    941941        return data or None 
    942942    html2python = staticmethod(html2python) 
    943943 
     944class IP6AddressField(IPAddressField): 
     945    def __init__(self, field_name, length=39, max_length=39, is_required=False, validator_list=None): 
     946        if validator_list is None: validator_list = [] 
     947        validator_list = [self.isValidIPAddress] + validator_list 
     948        TextField.__init__(self, field_name, length=length, max_length=max_length, 
     949            is_required=is_required, validator_list=validator_list) 
     950 
     951    def isValidIPAddress(self, field_data, all_data): 
     952        try: 
     953            validators.isValidIPAddress(field_data, all_data) 
     954        except validators.ValidationError, e: 
     955            raise validators.CriticalValidationError, e.messages 
     956 
     957    def html2python(data): 
     958        return data or None 
     959    html2python = staticmethod(html2python) 
     960 
    944961#################### 
    945962# MISCELLANEOUS    # 
    946963#################### 
  • django/db/models/fields/__init__.py

    old new  
    894894        defaults.update(kwargs) 
    895895        return super(IPAddressField, self).formfield(**defaults) 
    896896 
     897class IP6AddressField(Field): 
     898    empty_strings_allowed = False 
     899    def __init__(self, *args, **kwargs): 
     900        kwargs['max_length'] = 39 
     901        Field.__init__(self, *args, **kwargs) 
     902 
     903    def get_manipulator_field_objs(self): 
     904        return [oldforms.IP6AddressField] 
     905 
     906    def validate(self, field_data, all_data): 
     907        validators.isValidIPAddress(field_data, None) 
     908 
     909    def formfield(self, **kwargs): 
     910        defaults = {'form_class': forms.IP6AddressField} 
     911        defaults.update(kwargs) 
     912        return super(IP6AddressField, self).formfield(**defaults) 
     913 
     914 
    897915class NullBooleanField(Field): 
    898916    empty_strings_allowed = False 
    899917    def __init__(self, *args, **kwargs): 
  • django/db/backends/ado_mssql/creation.py

    old new  
    1212    'ImageField':        'varchar(%(max_length)s)', 
    1313    'IntegerField':      'int', 
    1414    'IPAddressField':    'char(15)', 
     15    'IP6AddressField':   'char(39)', 
    1516    'NullBooleanField':  'bit', 
    1617    'OneToOneField':     'int', 
    1718    'PhoneNumberField':  'varchar(20)', 
  • django/db/backends/postgresql/introspection.py

    old new  
    7575    23: 'IntegerField', 
    7676    25: 'TextField', 
    7777    701: 'FloatField', 
    78     869: 'IPAddressField', 
     78    869: 'IP6AddressField', 
    7979    1043: 'CharField', 
    8080    1082: 'DateField', 
    8181    1083: 'TimeField', 
  • django/db/backends/postgresql/creation.py

    old new  
    1616    'ImageField':        'varchar(%(max_length)s)', 
    1717    'IntegerField':      'integer', 
    1818    'IPAddressField':    'inet', 
     19    'IP6AddressField':   'inet', 
    1920    'NullBooleanField':  'boolean', 
    2021    'OneToOneField':     'integer', 
    2122    'PhoneNumberField':  'varchar(20)', 
  • django/db/backends/mysql_old/creation.py

    old new  
    1616    'ImageField':        'varchar(%(max_length)s)', 
    1717    'IntegerField':      'integer', 
    1818    'IPAddressField':    'char(15)', 
     19    'IP6AddressField':   'char(39)', 
    1920    'NullBooleanField':  'bool', 
    2021    'OneToOneField':     'integer', 
    2122    'PhoneNumberField':  'varchar(20)', 
  • django/db/backends/sqlite3/creation.py

    old new  
    1515    'ImageField':                   'varchar(%(max_length)s)', 
    1616    'IntegerField':                 'integer', 
    1717    'IPAddressField':               'char(15)', 
     18    'IP6AddressField':              'char(39)', 
    1819    'NullBooleanField':             'bool', 
    1920    'OneToOneField':                'integer', 
    2021    'PhoneNumberField':             'varchar(20)', 
  • django/db/backends/mysql/creation.py

    old new  
    1616    'ImageField':        'varchar(%(max_length)s)', 
    1717    'IntegerField':      'integer', 
    1818    'IPAddressField':    'char(15)', 
     19    'IPAddressField':    'char(39)', 
    1920    'NullBooleanField':  'bool', 
    2021    'OneToOneField':     'integer', 
    2122    'PhoneNumberField':  'varchar(20)', 
  • django/db/backends/oracle/creation.py

    old new  
    1919    'ImageField':                   'NVARCHAR2(%(max_length)s)', 
    2020    'IntegerField':                 'NUMBER(11)', 
    2121    'IPAddressField':               'VARCHAR2(15)', 
     22    'IP6AddressField':              'VARCHAR2(39)', 
    2223    'NullBooleanField':             'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))', 
    2324    'OneToOneField':                'NUMBER(11)', 
    2425    'PhoneNumberField':             'VARCHAR2(20)', 
  • django/db/backends/postgresql_psycopg2/introspection.py

    old new  
    7272    23: 'IntegerField', 
    7373    25: 'TextField', 
    7474    701: 'FloatField', 
    75     869: 'IPAddressField', 
     75    869: 'IP6AddressField', 
    7676    1043: 'CharField', 
    7777    1082: 'DateField', 
    7878    1083: 'TimeField', 
  • django/core/validators.py

    old new  
    106106        except ValidationError: 
    107107            raise ValidationError, _("Enter valid e-mail addresses separated by commas.") 
    108108 
    109 def isValidIPAddress4(field_data, all_data): 
     109def isValidIP4Address(field_data, all_data): 
    110110    if not ip4_re.search(field_data): 
     111        raise ValidationError, _("Please enter a valid IPv4 address.") 
     112 
     113def isValidIPAddress(field_data, all_data): 
     114    import IPy 
     115    try: 
     116        IPy.parseAddress(field_data) 
     117    except ValueError: 
    111118        raise ValidationError, _("Please enter a valid IP address.") 
    112119 
    113120def isNotEmpty(field_data, all_data): 
  • django/newforms/fields.py

    old new  
    1616except NameError: 
    1717    from sets import Set as set 
    1818 
     19import IPy 
     20 
    1921from django.utils.translation import ugettext_lazy as _ 
    2022from django.utils.encoding import StrAndUnicode, smart_unicode, smart_str 
    2123 
     
    3133    'RegexField', 'EmailField', 'FileField', 'ImageField', 'URLField', 
    3234    'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', 
    3335    'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', 
    34     'SplitDateTimeField', 'IPAddressField', 
     36    'SplitDateTimeField', 'IPAddressField', 'IP6AddressField', 
    3537) 
    3638 
    3739# These values, if given to to_python(), will trigger the self.required check. 
     
    754756 
    755757    def __init__(self, *args, **kwargs): 
    756758        super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs) 
     759 
     760class IP6AddressField(CharField): 
     761    def __init__(self, *args, **kwargs): 
     762        super(IP6AddressField, self).__init__(39, 3, *args, **kwargs) 
     763 
     764    def clean(self, value): 
     765        value = super(IP6AddressField, self).clean(value) 
     766        if value == u'': 
     767            return value 
     768        try: 
     769            IPy.parseAddress(value) 
     770        except ValueError: 
     771            raise ValidationError(_(u'Enter a valid IP address.')) 
     772        return value 
  • tests/regressiontests/forms/extra.py

    old new  
    310310... 
    311311ValidationError: [u'Enter a valid IPv4 address.'] 
    312312 
     313# IP6AddressField ################################################################## 
     314 
     315>>> f = IP6AddressField() 
     316>>> f.clean('') 
     317Traceback (most recent call last): 
     318... 
     319ValidationError: [u'This field is required.'] 
     320>>> f.clean(None) 
     321Traceback (most recent call last): 
     322... 
     323ValidationError: [u'This field is required.'] 
     324>>> f.clean('127.0.0.1') 
     325u'127.0.0.1' 
     326>>> f.clean('2a01:05d8:25ae:9451:020d:39bc:21e6:8cab') 
     327u'2a01:05d8:25ae:9451:020d:39bc:21e6:8cab' 
     328>>> f.clean('2a01:5d8:25ae:9451:20d:39bc:21e6:8cab') 
     329u'2a01:5d8:25ae:9451:20d:39bc:21e6:8cab' 
     330>>> f.clean('::1') 
     331u'::1' 
     332>>> f.clean('::ffff:88.191.32.1') 
     333u'::ffff:88.191.32.1' 
     334>>> f.clean('foo') 
     335Traceback (most recent call last): 
     336... 
     337ValidationError: [u'Enter a valid IP address.'] 
     338>>> f.clean('127.0.0.') 
     339Traceback (most recent call last): 
     340... 
     341ValidationError: [u'Enter a valid IP address.'] 
     342>>> f.clean('::1:') 
     343Traceback (most recent call last): 
     344... 
     345ValidationError: [u'Enter a valid IP address.'] 
     346>>> f.clean('1.2.3.4.5') 
     347Traceback (most recent call last): 
     348... 
     349ValidationError: [u'Enter a valid IP address.'] 
     350>>> f.clean('2a01:5d8:25ae:9451:20d:39bc:21e6:8cab:fb2c') 
     351Traceback (most recent call last): 
     352... 
     353ValidationError: [u'Ensure this value has at most 39 characters (it has 42).'] 
     354>>> f.clean('2a01:5d8:25ae:9451:20d:39bc:1e6:cab:b2c') 
     355Traceback (most recent call last): 
     356... 
     357ValidationError: [u'Enter a valid IP address.'] 
     358>>> f.clean('256.125.1.5') 
     359Traceback (most recent call last): 
     360... 
     361ValidationError: [u'Enter a valid IP address.'] 
     362>>> f.clean('::12345') 
     363Traceback (most recent call last): 
     364... 
     365ValidationError: [u'Enter a valid IP address.'] 
     366 
     367>>> f = IP6AddressField(required=False) 
     368>>> f.clean('') 
     369u'' 
     370>>> f.clean(None) 
     371u'' 
     372>>> f.clean('127.0.0.1') 
     373u'127.0.0.1' 
     374>>> f.clean('foo') 
     375Traceback (most recent call last): 
     376... 
     377ValidationError: [u'Enter a valid IP address.'] 
     378>>> f.clean('127.0.0.') 
     379Traceback (most recent call last): 
     380... 
     381ValidationError: [u'Enter a valid IP address.'] 
     382>>> f.clean('1.2.3.4.5') 
     383Traceback (most recent call last): 
     384... 
     385ValidationError: [u'Enter a valid IP address.'] 
     386>>> f.clean('256.125.1.5') 
     387Traceback (most recent call last): 
     388... 
     389ValidationError: [u'Enter a valid IP address.'] 
     390 
     391 
    313392################################# 
    314393# Tests of underlying functions # 
    315394################################# 
  • docs/newforms.txt

    old new  
    13901390      expression. 
    13911391    * Error message keys: ``required``, ``invalid`` 
    13921392 
     1393``IP6AddressField`` 
     1394~~~~~~~~~~~~~~~~~~ 
     1395 
     1396    * Default widget: ``TextInput`` 
     1397    * Empty value: ``''`` (an empty string) 
     1398    * Normalizes to: A Unicode object. 
     1399    * Validates that the given value is a valid IPv4 or IPv6 address, using 
     1400      IPy 
     1401    * Error message keys: ``required``, ``invalid`` 
     1402 
    13931403``MultipleChoiceField`` 
    13941404~~~~~~~~~~~~~~~~~~~~~~~ 
    13951405 
  • docs/model-api.txt

    old new  
    388388 
    389389The admin represents this as an ``<input type="text">`` (a single-line input). 
    390390 
     391``IP6AddressField`` 
     392~~~~~~~~~~~~~~~~~~ 
     393 
     394An IPv6 or IPv4 address, in string format (i.e. "24.124.1.30", 
     395"2002:58bf:278c::1", "::ffff:88.191.52.1"). 
     396 
     397The admin represents this as an ``<input type="text">`` (a single-line input). 
     398 
     399Requires `IPy`_. 
     400 
     401.. _IPy: http://software.inl.fr//trac/wiki/IPy 
     402 
    391403``NullBooleanField`` 
    392404~~~~~~~~~~~~~~~~~~~~ 
    393405 
  • docs/modelforms.txt

    old new  
    5858    ``ImageField``                   ``ImageField`` 
    5959    ``IntegerField``                 ``IntegerField`` 
    6060    ``IPAddressField``               ``IPAddressField`` 
     61    ``IP6AddressField``               ``IP6AddressField`` 
    6162    ``ManyToManyField``              ``ModelMultipleChoiceField`` (see 
    6263                                     below) 
    6364    ``NullBooleanField``             ``CharField`` 
  • docs/form_for_model.txt

    old new  
    6565    ``ImageField``                   ``ImageField`` 
    6666    ``IntegerField``                 ``IntegerField`` 
    6767    ``IPAddressField``               ``IPAddressField`` 
     68    ``IP6AddressField``               ``IP6AddressField`` 
    6869    ``ManyToManyField``              ``ModelMultipleChoiceField`` (see 
    6970                                     below) 
    7071    ``NullBooleanField``             ``CharField``