Skip to content

Commit d336496

Browse files
committedApr 17, 2015
Merge pull request jimfunk#35 from Antwan86/master
Django 1.7 and 1.8 support
2 parents fd8dddd + d892675 commit d336496

File tree

8 files changed

+346
-129
lines changed

8 files changed

+346
-129
lines changed
 

‎.travis.yml

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ env:
88
- DJANGO='Django<=1.4' PYSCOPG2='psycopg2==2.4.1' # see django issue #16250
99
- DJANGO='Django<=1.5' PYSCOPG2='psycopg2'
1010
- DJANGO='Django<=1.6' PYSCOPG2='psycopg2'
11+
- DJANGO='Django<=1.7' PYSCOPG2='psycopg2'
12+
- DJANGO='Django<=1.8' PYSCOPG2='psycopg2'
1113

1214
install:
1315
- pip install -q $PYSCOPG2 --use-mirrors
@@ -19,3 +21,10 @@ before_script:
1921
- psql -c 'create database netfields;' -U postgres
2022

2123
script: "./manage.py test"
24+
25+
matrix:
26+
exclude:
27+
- python: "2.6"
28+
env: DJANGO='Django<=1.7' PYSCOPG2='psycopg2'
29+
- python: "2.6"
30+
env: DJANGO='Django<=1.8' PYSCOPG2='psycopg2'

‎netfields/apps.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,39 @@
11
from django.apps import AppConfig
22

3+
from django.db.models.lookups import default_lookups
34
from netfields.fields import CidrAddressField, InetAddressField
4-
from netfields.lookups import NetContained, NetContains, NetContainedOrEqual, NetContainsOrEquals
5+
from netfields.lookups import NetContained, NetContains, NetContainedOrEqual, NetContainsOrEquals, InvalidLookup
6+
from netfields.lookups import EndsWith, IEndsWith, StartsWith, IStartsWith, Regex, IRegex
57

68

79
class NetfieldsConfig(AppConfig):
810
name = 'netfields'
911

12+
for lookup in default_lookups.keys():
13+
if lookup not in ['contains', 'startswith', 'endswith', 'icontains', 'istartswith', 'iendswith', 'isnull', 'in',
14+
'exact', 'iexact', 'regex', 'iregex', 'lt', 'lte', 'gt', 'gte', 'equals', 'iequals', 'range']:
15+
invalid_lookup = InvalidLookup
16+
invalid_lookup.lookup_name = lookup
17+
CidrAddressField.register_lookup(invalid_lookup)
18+
InetAddressField.register_lookup(invalid_lookup)
19+
20+
CidrAddressField.register_lookup(EndsWith)
21+
CidrAddressField.register_lookup(IEndsWith)
22+
CidrAddressField.register_lookup(StartsWith)
23+
CidrAddressField.register_lookup(IStartsWith)
24+
CidrAddressField.register_lookup(Regex)
25+
CidrAddressField.register_lookup(IRegex)
1026
CidrAddressField.register_lookup(NetContained)
1127
CidrAddressField.register_lookup(NetContains)
1228
CidrAddressField.register_lookup(NetContainedOrEqual)
1329
CidrAddressField.register_lookup(NetContainsOrEquals)
1430

31+
InetAddressField.register_lookup(EndsWith)
32+
InetAddressField.register_lookup(IEndsWith)
33+
InetAddressField.register_lookup(StartsWith)
34+
InetAddressField.register_lookup(IStartsWith)
35+
InetAddressField.register_lookup(Regex)
36+
InetAddressField.register_lookup(IRegex)
1537
InetAddressField.register_lookup(NetContained)
1638
InetAddressField.register_lookup(NetContains)
1739
InetAddressField.register_lookup(NetContainedOrEqual)

‎netfields/fields.py

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from netaddr import IPAddress, IPNetwork, EUI
22
from netaddr.core import AddrFormatError
33

4+
from django import VERSION
45
from django.db import models
56
from django.core.exceptions import ValidationError
67

@@ -35,7 +36,7 @@ def get_prep_lookup(self, lookup_type, value):
3536
NET_OPERATORS[lookup_type] not in NET_TEXT_OPERATORS):
3637
if lookup_type.startswith('net_contained') and value is not None:
3738
# Argument will be CIDR
38-
return unicode(value)
39+
return str(value)
3940
return self.get_prep_value(value)
4041

4142
return super(_NetAddressField, self).get_prep_lookup(
@@ -45,7 +46,7 @@ def get_prep_value(self, value):
4546
if not value:
4647
return None
4748

48-
return unicode(self.to_python(value))
49+
return str(self.to_python(value))
4950

5051
def get_db_prep_lookup(self, lookup_type, value, connection,
5152
prepared=False):
@@ -64,6 +65,12 @@ def formfield(self, **kwargs):
6465
defaults.update(kwargs)
6566
return super(_NetAddressField, self).formfield(**defaults)
6667

68+
if VERSION[:2] >= (1, 7):
69+
def deconstruct(self):
70+
name, path, args, kwargs = super(_NetAddressField, self).deconstruct()
71+
if self.max_length is not None:
72+
kwargs['max_length'] = self.max_length
73+
return name, path, args, kwargs
6774

6875

6976
class InetAddressField(_NetAddressField):
@@ -115,19 +122,20 @@ def get_prep_value(self, value):
115122
if not value:
116123
return None
117124

118-
return unicode(self.to_python(value))
125+
return str(self.to_python(value))
119126

120127
def formfield(self, **kwargs):
121128
defaults = {'form_class': MACAddressFormField}
122129
defaults.update(kwargs)
123130
return super(MACAddressField, self).formfield(**defaults)
124131

125-
try:
126-
from south.modelsinspector import add_introspection_rules
127-
add_introspection_rules([], [
128-
"^netfields\.fields\.InetAddressField",
129-
"^netfields\.fields\.CidrAddressField",
130-
"^netfields\.fields\.MACAddressField",
131-
])
132-
except ImportError:
133-
pass
132+
if VERSION[:2] < (1, 7):
133+
try:
134+
from south.modelsinspector import add_introspection_rules
135+
add_introspection_rules([], [
136+
"^netfields\.fields\.InetAddressField",
137+
"^netfields\.fields\.CidrAddressField",
138+
"^netfields\.fields\.MACAddressField",
139+
])
140+
except ImportError:
141+
pass

‎netfields/forms.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from netaddr import IPAddress, IPNetwork, EUI, AddrFormatError
22

33
from django import forms
4-
from django.utils.encoding import force_unicode
54
from django.utils.safestring import mark_safe
65
from django.core.exceptions import ValidationError
76

@@ -17,7 +16,7 @@ def render(self, name, value, attrs=None):
1716
value = ''
1817
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
1918
if value:
20-
final_attrs['value'] = force_unicode(value)
19+
final_attrs['value'] = value
2120
return mark_safe(u'<input%s />' % forms.util.flatatt(final_attrs))
2221

2322

@@ -39,7 +38,7 @@ def to_python(self, value):
3938

4039
try:
4140
return IPAddress(value)
42-
except (AddrFormatError, TypeError), e:
41+
except (AddrFormatError, TypeError) as e:
4342
raise ValidationError(str(e))
4443

4544

@@ -61,7 +60,7 @@ def to_python(self, value):
6160

6261
try:
6362
return IPNetwork(value)
64-
except (AddrFormatError, TypeError), e:
63+
except (AddrFormatError, TypeError) as e:
6564
raise ValidationError(str(e))
6665

6766

‎netfields/lookups.py

+43-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,47 @@
11
from django.db.models import Lookup
2-
from django.db.models.lookups import IExact, IContains
2+
from django.db.models.lookups import BuiltinLookup
3+
from netfields.fields import InetAddressField, CidrAddressField
4+
5+
6+
class InvalidLookup(BuiltinLookup):
7+
def as_sql(self, qn, connection):
8+
raise ValueError('Invalid lookup type "%s"' % self.lookup_name)
9+
10+
11+
class NetFieldDecoratorMixin(object):
12+
def process_lhs(self, qn, connection, lhs=None):
13+
lhs = lhs or self.lhs
14+
lhs_string, lhs_params = qn.compile(lhs)
15+
if isinstance(lhs.source if hasattr(lhs, 'source') else lhs.output_field, InetAddressField):
16+
lhs_string = 'HOST(%s)' % lhs_string
17+
elif isinstance(lhs.source if hasattr(lhs, 'source') else lhs.output_field, CidrAddressField):
18+
lhs_string = 'TEXT(%s)' % lhs_string
19+
return lhs_string, lhs_params
20+
21+
22+
class EndsWith(NetFieldDecoratorMixin, BuiltinLookup):
23+
lookup_name = 'endswith'
24+
25+
26+
class IEndsWith(NetFieldDecoratorMixin, BuiltinLookup):
27+
lookup_name = 'iendswith'
28+
29+
30+
class StartsWith(NetFieldDecoratorMixin, BuiltinLookup):
31+
lookup_name = 'startswith'
32+
33+
34+
class IStartsWith(NetFieldDecoratorMixin, BuiltinLookup):
35+
lookup_name = 'istartswith'
36+
37+
38+
class Regex(NetFieldDecoratorMixin, BuiltinLookup):
39+
lookup_name = 'regex'
40+
41+
42+
class IRegex(NetFieldDecoratorMixin, BuiltinLookup):
43+
lookup_name = 'iregex'
44+
345

446
class NetContains(Lookup):
547
lookup_name = 'net_contains'
@@ -38,4 +80,3 @@ def as_sql(self, qn, connection):
3880
rhs, rhs_params = self.process_rhs(qn, connection)
3981
params = lhs_params + rhs_params
4082
return '%s <<= %s' % (lhs, rhs), params
41-

‎netfields/managers.py

+54-49
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ def _prepare_data(self, data):
4848
# emptiness and transform any non-empty values correctly.
4949
value = list(value)
5050

51-
5251
# The "value_annotation" parameter is used to pass auxilliary information
5352
# about the value(s) to the query construction. Specifically, datetime
5453
# and empty values need special handling. Other types could be used
@@ -101,64 +100,70 @@ def add(self, data, connector):
101100
tree.Node.add(self,
102101
(obj, lookup_type, value_annotation, value), connector)
103102

104-
def make_atom(self, child, qn, conn):
105-
lvalue, lookup_type, value_annot, params_or_value = child
106-
107-
if hasattr(lvalue, 'process'):
108-
try:
109-
lvalue, params = lvalue.process(lookup_type, params_or_value,
110-
connection)
111-
except sql.where.EmptyShortCircuit:
112-
raise query.EmptyResultSet
113-
else:
114-
return super(NetWhere, self).make_atom(child, qn, conn)
103+
if VERSION[:2] < (1, 7):
104+
def make_atom(self, child, qn, conn):
105+
lvalue, lookup_type, value_annot, params_or_value = child
115106

116-
table_alias, name, db_type = lvalue
107+
if hasattr(lvalue, 'process'):
108+
try:
109+
lvalue, params = lvalue.process(lookup_type, params_or_value,
110+
connection)
111+
except sql.where.EmptyShortCircuit:
112+
raise query.EmptyResultSet
113+
else:
114+
return super(NetWhere, self).make_atom(child, qn, conn)
117115

118-
if db_type not in ['inet', 'cidr']:
119-
return super(NetWhere, self).make_atom(child, qn, conn)
116+
table_alias, name, db_type = lvalue
120117

121-
if table_alias:
122-
field_sql = '%s.%s' % (qn(table_alias), qn(name))
123-
else:
124-
field_sql = qn(name)
118+
if db_type not in ['inet', 'cidr']:
119+
return super(NetWhere, self).make_atom(child, qn, conn)
125120

126-
if NET_OPERATORS.get(lookup_type, '') in NET_TEXT_OPERATORS:
127-
if db_type == 'inet':
128-
field_sql = 'HOST(%s)' % field_sql
121+
if table_alias:
122+
field_sql = '%s.%s' % (qn(table_alias), qn(name))
129123
else:
130-
field_sql = 'TEXT(%s)' % field_sql
124+
field_sql = qn(name)
131125

132-
if isinstance(params, QueryWrapper):
133-
extra, params = params.data
134-
else:
135-
extra = ''
136-
137-
if isinstance(params, basestring):
138-
params = (params,)
139-
140-
if lookup_type in NET_OPERATORS:
141-
return (' '.join([field_sql, NET_OPERATORS[lookup_type], extra]),
142-
params)
143-
elif lookup_type == 'in':
144-
if not value_annot:
145-
raise sql.datastructures.EmptyResultSet
146-
if extra:
147-
return ('%s IN %s' % (field_sql, extra), params)
148-
return ('%s IN (%s)' % (field_sql, ', '.join(['%s'] *
149-
len(params))), params)
150-
elif lookup_type == 'range':
151-
return ('%s BETWEEN %%s and %%s' % field_sql, params)
152-
elif lookup_type == 'isnull':
153-
return ('%s IS %sNULL' % (field_sql, (not value_annot and 'NOT ' or
154-
'')), params)
155-
156-
raise ValueError('Invalid lookup type "%s"' % lookup_type)
126+
if NET_OPERATORS.get(lookup_type, '') in NET_TEXT_OPERATORS:
127+
if db_type == 'inet':
128+
field_sql = 'HOST(%s)' % field_sql
129+
else:
130+
field_sql = 'TEXT(%s)' % field_sql
131+
132+
if isinstance(params, QueryWrapper):
133+
extra, params = params.data
134+
else:
135+
extra = ''
136+
137+
if isinstance(params, basestring):
138+
params = (params,)
139+
140+
if lookup_type in NET_OPERATORS:
141+
return (' '.join([field_sql, NET_OPERATORS[lookup_type], extra]),
142+
params)
143+
elif lookup_type == 'in':
144+
if not value_annot:
145+
raise sql.datastructures.EmptyResultSet
146+
if extra:
147+
return ('%s IN %s' % (field_sql, extra), params)
148+
return ('%s IN (%s)' % (field_sql, ', '.join(['%s'] *
149+
len(params))), params)
150+
elif lookup_type == 'range':
151+
return ('%s BETWEEN %%s and %%s' % field_sql, params)
152+
elif lookup_type == 'isnull':
153+
return ('%s IS %sNULL' % (field_sql, (not value_annot and 'NOT ' or
154+
'')), params)
155+
156+
raise ValueError('Invalid lookup type "%s"' % lookup_type)
157157

158158

159159
class NetManager(models.Manager):
160160
use_for_related_fields = True
161161

162-
def get_query_set(self):
162+
def get_queryset(self):
163163
q = NetQuery(self.model, NetWhere)
164164
return query.QuerySet(self.model, q)
165+
166+
if VERSION[:2] < (1, 6):
167+
def get_query_set(self):
168+
q = NetQuery(self.model, NetWhere)
169+
return query.QuerySet(self.model, q)

0 commit comments

Comments
 (0)
Please sign in to comment.