from django.db import models from django.utils.text import compress_string from django.db.models import signals from django.dispatch import dispatcher def uncompress_string(s): '''helper function to reverse django.utils.text.compress_string''' import cStringIO, gzip try: zbuf = cStringIO.StringIO(s) zfile = gzip.GzipFile(fileobj=zbuf) ret = zfile.read() zfile.close() except: ret = s return ret class CompressedTextField(models.TextField): '''transparently compress data before hitting the db and uncompress after fetching''' def get_db_prep_save(self, value): if value is not None: value = compress_string(value) return models.TextField.get_db_prep_save(self, value) def _get_val_from_obj(self, obj): if obj: return uncompress_string(getattr(obj, self.attname)) else: return self.get_default() def post_init(self, instance=None): value = self._get_val_from_obj(instance) if value: setattr(instance, self.attname, value) def contribute_to_class(self, cls, name): super(CompressedTextField, self).contribute_to_class(cls, name) dispatcher.connect(self.post_init, signal=signals.post_init, sender=cls) def get_internal_type(self): return "TextField" def db_type(self): from django.conf import settings if settings.DATABASE_ENGINE == 'mysql': return 'longblob' else: raise Exception, '%s currently works only with MySQL'%self.__class__.__name__ class Item(models.Model): title = models.CharField(maxlength=200) summary = CompressedTextField(blank=True)