Code

Ticket #1636: django_cidr.diff

File django_cidr.diff, 6.1 KB (added by Rob Shakir (rob@…, 8 years ago)

CIDR Patch for Django

Line 
1Index: django/db/models/fields/__init__.py
2===================================================================
3--- django/db/models/fields/__init__.py (revision 2693)
4+++ django/db/models/fields/__init__.py (working copy)
5@@ -670,6 +670,17 @@
6     def validate(self, field_data, all_data):
7         validators.isValidIPAddress4(field_data, None)
8 
9+class CIDRAddressField(Field):
10+    def __init__(self, *args, **kwargs):
11+       kwargs['maxlength'] = 18
12+       Field.__init__(self, *args, **kwargs)
13+
14+    def get_manipulator_field_objs(self):
15+       return [forms.CIDRAddressField]
16+
17+    def valid(self, field_data, all_data):
18+       validators.isValidCIDRAddress4(field_data, None)
19+
20 class NullBooleanField(Field):
21     def __init__(self, *args, **kwargs):
22         kwargs['null'] = True
23Index: django/db/backends/ado_mssql/creation.py
24===================================================================
25--- django/db/backends/ado_mssql/creation.py    (revision 2693)
26+++ django/db/backends/ado_mssql/creation.py    (working copy)
27@@ -11,6 +11,7 @@
28     'ImageField':        'varchar(100)',
29     'IntegerField':      'int',
30     'IPAddressField':    'char(15)',
31+    'CIDRAddressField':  'char(18)',
32     'ManyToManyField':   None,
33     'NullBooleanField':  'bit',
34     'OneToOneField':     'int',
35Index: django/db/backends/postgresql/introspection.py
36===================================================================
37--- django/db/backends/postgresql/introspection.py      (revision 2693)
38+++ django/db/backends/postgresql/introspection.py      (working copy)
39@@ -74,6 +74,7 @@
40     21: 'SmallIntegerField',
41     23: 'IntegerField',
42     25: 'TextField',
43+    650: 'CIDRAddressField',
44     869: 'IPAddressField',
45     1043: 'CharField',
46     1082: 'DateField',
47Index: django/db/backends/postgresql/creation.py
48===================================================================
49--- django/db/backends/postgresql/creation.py   (revision 2693)
50+++ django/db/backends/postgresql/creation.py   (working copy)
51@@ -15,6 +15,7 @@
52     'ImageField':        'varchar(100)',
53     'IntegerField':      'integer',
54     'IPAddressField':    'inet',
55+    'CIDRAddressField':  'cidr',
56     'ManyToManyField':   None,
57     'NullBooleanField':  'boolean',
58     'OneToOneField':     'integer',
59Index: django/db/backends/sqlite3/creation.py
60===================================================================
61--- django/db/backends/sqlite3/creation.py      (revision 2693)
62+++ django/db/backends/sqlite3/creation.py      (working copy)
63@@ -14,6 +14,7 @@
64     'ImageField':                   'varchar(100)',
65     'IntegerField':                 'integer',
66     'IPAddressField':               'char(15)',
67+    'CIDRAddressField':             'char(18)',
68     'ManyToManyField':              None,
69     'NullBooleanField':             'bool',
70     'OneToOneField':                'integer',
71Index: django/db/backends/mysql/creation.py
72===================================================================
73--- django/db/backends/mysql/creation.py        (revision 2693)
74+++ django/db/backends/mysql/creation.py        (working copy)
75@@ -15,6 +15,7 @@
76     'ImageField':        'varchar(100)',
77     'IntegerField':      'integer',
78     'IPAddressField':    'char(15)',
79+    'CIDRAddressField':  'char(18)',
80     'ManyToManyField':   None,
81     'NullBooleanField':  'bool',
82     'OneToOneField':     'integer',
83Index: django/forms/__init__.py
84===================================================================
85--- django/forms/__init__.py    (revision 2693)
86+++ django/forms/__init__.py    (working copy)
87@@ -863,6 +863,17 @@
88         return data or None
89     html2python = staticmethod(html2python)
90 
91+class CIDRAddressField(TextField):
92+    def __init__(self, field_name, length=18, maxlength=18, is_required=False, validator_list=[]):
93+       validator_list = [self.isValidCIDRAddress] + validator_list
94+       TextField.__init__(self, field_name, length=length, maxlength=maxlength,            is_required=is_required, validator_list=validator_list)
95+
96+    def isValidCIDRAddress(self, field_data, all_data):
97+       try:
98+          validators.isValidCIDRAddress4(field_data, all_data)
99+       except validators.ValidationError, e:
100+          raise validators.CriticalValidationError, e.messages
101+
102 ####################
103 # MISCELLANEOUS    #
104 ####################
105Index: django/core/validators.py
106===================================================================
107--- django/core/validators.py   (revision 2693)
108+++ django/core/validators.py   (working copy)
109@@ -23,6 +23,7 @@
110 email_re = re.compile(r'^[A-Z0-9._%-][+A-Z0-9._%-]*@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$', re.IGNORECASE)
111 integer_re = re.compile(r'^-?\d+$')
112 ip4_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}$')
113+ip4_cidr_re = re.compile(r'^([0-9]|1?\d\d|2[0-4]\d|25[0-5])\.([0-9]|1?\d\d|2[0-4]\d|25[0-5])\.([0-9]|1?\d\d|2[0-4]\d|25[0-5])\.([0-9]|1?\d\d|2[0-4]\d|25[0-5])(\/([1-9]|1\d|2\d|3[0-2]))$')
114 phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)
115 slug_re = re.compile(r'^[-\w]+$')
116 url_re = re.compile(r'^https?://\S+$')
117@@ -98,6 +99,31 @@
118     if not ip4_re.search(field_data):
119         raise ValidationError, gettext("Please enter a valid IP address.")
120 
121+def isValidCIDRAddress4(field_data, all_data):
122+    if not ip4_cidr_re.search(field_data):
123+       raise ValidationError, gettext("Please enter a valid CIDR address.")
124+    cidr_parts = field_data.split('/')
125+    if not 0 <= int(cidr_parts[1]) <= 32:
126+       raise ValidationError, gettext("CIDR Mask not in valid range.")
127+    inet_octets = cidr_parts[0].split('.')
128+    inet_dec = 0L
129+    inet_dec = inet_dec | (long(inet_octets[0]) << 24)
130+    inet_dec = inet_dec | (long(inet_octets[1]) << 16)
131+    inet_dec = inet_dec | (long(inet_octets[2]) << 8)
132+    inet_dec = inet_dec | (long(inet_octets[3]))
133+
134+    inet_bin = ''
135+    for i in xrange(0, 32):
136+        if inet_dec & 1:
137+           inet_bin = '1' + inet_bin
138+        else:
139+           inet_bin = '0' + inet_bin
140+        inet_dec = inet_dec >> 1
141+    for i in range(int(cidr_parts[1]), 32):
142+       if int(inet_bin[i]) == 1:
143+          raise ValidationError, gettext("CIDR addresses must not have host bits.")
144+   
145+
146 def isNotEmpty(field_data, all_data):
147     if field_data.strip() == '':
148         raise ValidationError, gettext("Empty values are not allowed here.")
149