lookups.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. from __future__ import unicode_literals
  2. from django.db.models import Lookup, Transform, IntegerField
  3. from django.db.models import lookups
  4. class NetFieldDecoratorMixin(object):
  5. def process_lhs(self, qn, connection, lhs=None):
  6. lhs = lhs or self.lhs
  7. lhs_string, lhs_params = qn.compile(lhs)
  8. lhs_string = 'TEXT(%s)' % lhs_string
  9. return lhs_string, lhs_params
  10. class EndsWith(NetFieldDecoratorMixin, lookups.EndsWith):
  11. lookup_name = 'endswith'
  12. class IEndsWith(NetFieldDecoratorMixin, lookups.IEndsWith):
  13. lookup_name = 'iendswith'
  14. class StartsWith(NetFieldDecoratorMixin, lookups.StartsWith):
  15. lookup_name = 'startswith'
  16. class IStartsWith(NetFieldDecoratorMixin, lookups.IStartsWith):
  17. lookup_name = 'istartswith'
  18. class Regex(NetFieldDecoratorMixin, lookups.Regex):
  19. lookup_name = 'regex'
  20. class IRegex(NetFieldDecoratorMixin, lookups.IRegex):
  21. lookup_name = 'iregex'
  22. class NetContainsOrEquals(Lookup):
  23. lookup_name = 'net_contains_or_equals'
  24. def as_sql(self, qn, connection):
  25. lhs, lhs_params = self.process_lhs(qn, connection)
  26. rhs, rhs_params = self.process_rhs(qn, connection)
  27. params = lhs_params + rhs_params
  28. return '%s >>= %s' % (lhs, rhs), params
  29. class NetContains(Lookup):
  30. lookup_name = 'net_contains'
  31. def as_sql(self, qn, connection):
  32. lhs, lhs_params = self.process_lhs(qn, connection)
  33. rhs, rhs_params = self.process_rhs(qn, connection)
  34. params = lhs_params + rhs_params
  35. return '%s >> %s' % (lhs, rhs), params
  36. class NetContained(Lookup):
  37. lookup_name = 'net_contained'
  38. def as_sql(self, qn, connection):
  39. lhs, lhs_params = self.process_lhs(qn, connection)
  40. rhs, rhs_params = self.process_rhs(qn, connection)
  41. params = lhs_params + rhs_params
  42. return '%s << %s' % (lhs, rhs), params
  43. class NetContainedOrEqual(Lookup):
  44. lookup_name = 'net_contained_or_equal'
  45. def as_sql(self, qn, connection):
  46. lhs, lhs_params = self.process_lhs(qn, connection)
  47. rhs, rhs_params = self.process_rhs(qn, connection)
  48. params = lhs_params + rhs_params
  49. return '%s <<= %s' % (lhs, rhs), params
  50. class NetHost(Lookup):
  51. lookup_name = 'net_host'
  52. def as_sql(self, qn, connection):
  53. lhs, lhs_params = self.process_lhs(qn, connection)
  54. rhs, rhs_params = self.process_rhs(qn, connection)
  55. # Query parameters are automatically converted to IPNetwork objects, which are then turned to strings. We need
  56. # to omit the mask portion of the object's string representation to match PostgreSQL's HOST() function.
  57. if rhs_params:
  58. rhs_params[0] = rhs_params[0].split('/')[0]
  59. params = lhs_params + rhs_params
  60. return 'HOST(%s) = %s' % (lhs, rhs), params
  61. class NetHostContained(Lookup):
  62. """
  63. Check for the host portion of an IP address without regard to its mask. This allows us to find e.g. 192.0.2.1/24
  64. when specifying a parent prefix of 192.0.2.0/26.
  65. """
  66. lookup_name = 'net_host_contained'
  67. def as_sql(self, qn, connection):
  68. lhs, lhs_params = self.process_lhs(qn, connection)
  69. rhs, rhs_params = self.process_rhs(qn, connection)
  70. params = lhs_params + rhs_params
  71. return 'CAST(HOST(%s) AS INET) << %s' % (lhs, rhs), params
  72. class NetMaskLength(Transform):
  73. lookup_name = 'net_mask_length'
  74. function = 'MASKLEN'
  75. @property
  76. def output_field(self):
  77. return IntegerField()