fields.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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 EUI, AddrFormatError, 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 get_internal_type(self):
  26. return 'CharField'
  27. def to_python(self, value):
  28. if value is None:
  29. return value
  30. if type(value) is str:
  31. value = value.replace(' ', '')
  32. try:
  33. return EUI(value, version=48, dialect=mac_unix_expanded_uppercase)
  34. except AddrFormatError:
  35. raise ValidationError(_("Invalid MAC address format: {value}").format(value=value))
  36. def db_type(self, connection):
  37. return 'macaddr'
  38. def get_prep_value(self, value):
  39. if not value:
  40. return None
  41. return str(self.to_python(value))
  42. class WWNField(models.Field):
  43. description = 'World Wide Name field'
  44. def python_type(self):
  45. return EUI
  46. def from_db_value(self, value, expression, connection):
  47. return self.to_python(value)
  48. def get_internal_type(self):
  49. return 'CharField'
  50. def to_python(self, value):
  51. if value is None:
  52. return value
  53. try:
  54. return EUI(value, version=64, dialect=eui64_unix_expanded_uppercase)
  55. except AddrFormatError:
  56. raise ValidationError(_("Invalid WWN format: {value}").format(value=value))
  57. def db_type(self, connection):
  58. return 'macaddr8'
  59. def get_prep_value(self, value):
  60. if not value:
  61. return None
  62. return str(self.to_python(value))
  63. class PathField(ArrayField):
  64. """
  65. An ArrayField which holds a set of objects, each identified by a (type, ID) tuple.
  66. """
  67. def __init__(self, **kwargs):
  68. kwargs['base_field'] = models.CharField(max_length=40)
  69. super().__init__(**kwargs)
  70. PathField.register_lookup(PathContains)