fields.py 2.2 KB

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