fields.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from django.contrib.postgres.fields import ArrayField
  2. from django.core.exceptions import ValidationError
  3. from django.db import models
  4. from django.utils.translation import gettext as _
  5. from netaddr import AddrFormatError, EUI, eui64_unix_expanded, mac_unix_expanded
  6. from .lookups import PathContains
  7. __all__ = (
  8. 'MACAddressField',
  9. 'PathField',
  10. 'WWNField',
  11. )
  12. class mac_unix_expanded_uppercase(mac_unix_expanded):
  13. word_fmt = '%.2X'
  14. class eui64_unix_expanded_uppercase(eui64_unix_expanded):
  15. word_fmt = '%.2X'
  16. #
  17. # Fields
  18. #
  19. class MACAddressField(models.Field):
  20. description = "PostgreSQL MAC Address field"
  21. def python_type(self):
  22. return EUI
  23. def from_db_value(self, value, expression, connection):
  24. return self.to_python(value)
  25. def to_python(self, value):
  26. if value is None:
  27. return value
  28. if type(value) is str:
  29. value = value.replace(' ', '')
  30. try:
  31. return EUI(value, version=48, dialect=mac_unix_expanded_uppercase)
  32. except AddrFormatError:
  33. raise ValidationError(_("Invalid MAC address format: {value}").format(value=value))
  34. def db_type(self, connection):
  35. return 'macaddr'
  36. def get_prep_value(self, value):
  37. if not value:
  38. return None
  39. return str(self.to_python(value))
  40. class WWNField(models.Field):
  41. description = "World Wide Name field"
  42. def python_type(self):
  43. return EUI
  44. def from_db_value(self, value, expression, connection):
  45. return self.to_python(value)
  46. def to_python(self, value):
  47. if value is None:
  48. return value
  49. try:
  50. return EUI(value, version=64, dialect=eui64_unix_expanded_uppercase)
  51. except AddrFormatError:
  52. raise ValidationError(_("Invalid WWN format: {value}").format(value=value))
  53. def db_type(self, connection):
  54. return 'macaddr8'
  55. def get_prep_value(self, value):
  56. if not value:
  57. return None
  58. return str(self.to_python(value))
  59. class PathField(ArrayField):
  60. """
  61. An ArrayField which holds a set of objects, each identified by a (type, ID) tuple.
  62. """
  63. def __init__(self, **kwargs):
  64. kwargs['base_field'] = models.CharField(max_length=40)
  65. super().__init__(**kwargs)
  66. PathField.register_lookup(PathContains)