fields.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. from django.core.exceptions import ValidationError
  2. from django.db import models
  3. from netaddr import AddrFormatError, IPNetwork, IPAddress
  4. from . import lookups
  5. from .formfields import IPFormField
  6. def prefix_validator(prefix):
  7. if prefix.ip != prefix.cidr.ip:
  8. raise ValidationError("{} is not a valid prefix. Did you mean {}?".format(prefix, prefix.cidr))
  9. class BaseIPField(models.Field):
  10. def python_type(self):
  11. return IPNetwork
  12. def from_db_value(self, value, expression, connection):
  13. return self.to_python(value)
  14. def to_python(self, value):
  15. if not value:
  16. return value
  17. try:
  18. if '/' in str(value):
  19. return IPNetwork(value)
  20. else:
  21. return IPAddress(value)
  22. except AddrFormatError as e:
  23. raise ValidationError("Invalid IP address format: {}".format(value))
  24. except (TypeError, ValueError) as e:
  25. raise ValidationError(e)
  26. def get_prep_value(self, value):
  27. if not value:
  28. return None
  29. if isinstance(value, list):
  30. return [str(self.to_python(v)) for v in value]
  31. return str(self.to_python(value))
  32. def form_class(self):
  33. return IPFormField
  34. def formfield(self, **kwargs):
  35. defaults = {'form_class': self.form_class()}
  36. defaults.update(kwargs)
  37. return super().formfield(**defaults)
  38. class IPNetworkField(BaseIPField):
  39. """
  40. IP prefix (network and mask)
  41. """
  42. description = "PostgreSQL CIDR field"
  43. default_validators = [prefix_validator]
  44. def db_type(self, connection):
  45. return 'cidr'
  46. IPNetworkField.register_lookup(lookups.IExact)
  47. IPNetworkField.register_lookup(lookups.EndsWith)
  48. IPNetworkField.register_lookup(lookups.IEndsWith)
  49. IPNetworkField.register_lookup(lookups.StartsWith)
  50. IPNetworkField.register_lookup(lookups.IStartsWith)
  51. IPNetworkField.register_lookup(lookups.Regex)
  52. IPNetworkField.register_lookup(lookups.IRegex)
  53. IPNetworkField.register_lookup(lookups.NetContained)
  54. IPNetworkField.register_lookup(lookups.NetContainedOrEqual)
  55. IPNetworkField.register_lookup(lookups.NetContains)
  56. IPNetworkField.register_lookup(lookups.NetContainsOrEquals)
  57. IPNetworkField.register_lookup(lookups.NetMaskLength)
  58. class IPAddressField(BaseIPField):
  59. """
  60. IP address (host address and mask)
  61. """
  62. description = "PostgreSQL INET field"
  63. def db_type(self, connection):
  64. return 'inet'
  65. IPAddressField.register_lookup(lookups.IExact)
  66. IPAddressField.register_lookup(lookups.EndsWith)
  67. IPAddressField.register_lookup(lookups.IEndsWith)
  68. IPAddressField.register_lookup(lookups.StartsWith)
  69. IPAddressField.register_lookup(lookups.IStartsWith)
  70. IPAddressField.register_lookup(lookups.Regex)
  71. IPAddressField.register_lookup(lookups.IRegex)
  72. IPAddressField.register_lookup(lookups.NetContained)
  73. IPAddressField.register_lookup(lookups.NetContainedOrEqual)
  74. IPAddressField.register_lookup(lookups.NetContains)
  75. IPAddressField.register_lookup(lookups.NetContainsOrEquals)
  76. IPAddressField.register_lookup(lookups.NetHost)
  77. IPAddressField.register_lookup(lookups.NetHostIn)
  78. IPAddressField.register_lookup(lookups.NetHostContained)
  79. IPAddressField.register_lookup(lookups.NetMaskLength)