fields.py 3.0 KB

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