fields.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. """
  2. Custom Django Model Fields.
  3. """
  4. from django.db import models
  5. try:
  6. import cPickle as pickle
  7. except ImportError:
  8. import pickle
  9. class PickledObject(str):
  10. """A subclass of string so it can be told whether a string is
  11. a pickled object or not (if the object is an instance of this class
  12. then it must [well, should] be a pickled one)."""
  13. pass
  14. class PickledObjectField(models.Field):
  15. """A field that automatically pickles/unpickles its value."""
  16. __metaclass__ = models.SubfieldBase
  17. def to_python(self, value):
  18. """Convert the database value to a python value."""
  19. if isinstance(value, PickledObject):
  20. # If the value is a definite pickle; and an error is
  21. # raised in de-pickling it should be allowed to propogate.
  22. return pickle.loads(str(value))
  23. else:
  24. try:
  25. return pickle.loads(str(value))
  26. except pickle.PickleError:
  27. # If an error was raised, just return the plain value
  28. return value
  29. def get_db_prep_save(self, value):
  30. """get_db_prep_save"""
  31. if value is not None and not isinstance(value, PickledObject):
  32. value = PickledObject(pickle.dumps(value))
  33. return value
  34. def get_internal_type(self):
  35. """The database field type used by this field."""
  36. return 'TextField'
  37. def get_db_prep_lookup(self, lookup_type, value):
  38. """get_db_prep_lookup"""
  39. if lookup_type == 'exact':
  40. value = self.get_db_prep_save(value)
  41. return super(PickledObjectField, self).get_db_prep_lookup(
  42. lookup_type, value)
  43. elif lookup_type == 'in':
  44. value = [self.get_db_prep_save(v) for v in value]
  45. return super(PickledObjectField, self).get_db_prep_lookup(
  46. lookup_type, value)
  47. else:
  48. raise TypeError('Lookup type %s is not supported.' % lookup_type)