fields.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. from django.core.validators import RegexValidator
  2. from django.db import models
  3. from utilities.ordering import naturalize
  4. from .forms import ColorSelect
  5. ColorValidator = RegexValidator(
  6. regex='^[0-9a-f]{6}$',
  7. message='Enter a valid hexadecimal RGB color code.',
  8. code='invalid'
  9. )
  10. # Deprecated: Retained only to ensure successful migration from early releases
  11. # Use models.CharField(null=True) instead
  12. class NullableCharField(models.CharField):
  13. description = "Stores empty values as NULL rather than ''"
  14. def to_python(self, value):
  15. if isinstance(value, models.CharField):
  16. return value
  17. return value or ''
  18. def get_prep_value(self, value):
  19. return value or None
  20. class ColorField(models.CharField):
  21. default_validators = [ColorValidator]
  22. description = "A hexadecimal RGB color code"
  23. def __init__(self, *args, **kwargs):
  24. kwargs['max_length'] = 6
  25. super().__init__(*args, **kwargs)
  26. def formfield(self, **kwargs):
  27. kwargs['widget'] = ColorSelect
  28. return super().formfield(**kwargs)
  29. class NaturalOrderingField(models.CharField):
  30. """
  31. A field which stores a naturalized representation of its target field, to be used for ordering its parent model.
  32. :param target_field: Name of the field of the parent model to be naturalized
  33. :param naturalize_function: The function used to generate a naturalized value (optional)
  34. """
  35. description = "Stores a representation of its target field suitable for natural ordering"
  36. def __init__(self, target_field, naturalize_function=naturalize, *args, **kwargs):
  37. self.target_field = target_field
  38. self.naturalize_function = naturalize_function
  39. super().__init__(*args, **kwargs)
  40. def pre_save(self, model_instance, add):
  41. """
  42. Generate a naturalized value from the target field
  43. """
  44. original_value = getattr(model_instance, self.target_field)
  45. naturalized_value = self.naturalize_function(original_value, max_length=self.max_length)
  46. setattr(model_instance, self.attname, naturalized_value)
  47. return naturalized_value
  48. def deconstruct(self):
  49. kwargs = super().deconstruct()[3] # Pass kwargs from CharField
  50. kwargs['naturalize_function'] = self.naturalize_function
  51. return (
  52. self.name,
  53. 'utilities.fields.NaturalOrderingField',
  54. [self.target_field],
  55. kwargs,
  56. )