2013-05-09 3 views
1

У меня есть байтовая строка, которую нужно хранить.Необходимо сохранить bytestring с помощью Django

Поскольку Django не поддерживает BlobFields, я думал, что создам свой собственный Base64Field, , который кодирует и декодирует base64 при взаимодействии с db. Итак, я перевернул (?) Методы to_python и get_db_prep_save для этой точной цели.

Проблема в том, что to_python вызывается в разных сценариях, а не только один раз и нет способа определить, была ли строка уже декодирована или нет. Очевидно, что если он уже декодирован, то возникает ошибка .

Какие решения существуют для моей дилемы?

Возможные решения, которые кажутся уродливой мне: попробовать, кроме процесса декодирования, возвращаемое значение, если декодирование не удается, используя переменную экземпляра только позволяют 1 to_python (это, кажется, еще хуже)

+0

Не могли бы вы показать методы? –

ответ

0

Вы можете использовать какой-то PickledObjectField ,

class PickledObjectField(models.Field): 
    __metaclass__ = models.SubfieldBase 

    marker_re = re.compile(r'^T\[(?P<type>\w+)\](?P<value>.*)$', re.DOTALL) 
    markable_types = dict((t.__name__, t) for t in (str, int, unicode)) 

    def __init__(self, *args, **kwargs): 
     self.compress = kwargs.pop('compress', True) 
     self.protocol = kwargs.pop('protocol', 2) 
     kwargs.setdefault('null', True) 
     kwargs.setdefault('editable', False) 
     super(PickledObjectField, self).__init__(*args, **kwargs) 

    def generate_type_marked_value(self, value): 
     return PickledObject(u"T[%s]%s" % (type(value).__name__, value)) 

    def read_marked_value(self, value): 
     m = self.marker_re.match(value) 

     if m: 
      marker = m.group('type') 
      value = m.group('value') 
      if marker in self.markable_types: 
       value = self.markable_types[marker](value) 

     return value 

    def get_default(self): 
     if self.has_default(): 
      if callable(self.default): 
       return self.default() 
      return self.default 

     return super(PickledObjectField, self).get_default() 

    def to_python(self, value): 
     if value is not None: 
      try: 
       if value.startswith("T["): 
        value = self.read_marked_value(value) 
       else: 
        value = dbsafe_decode(value, self.compress) 
      except: 
       if isinstance(value, PickledObject): 
        raise 
     return value 

    def get_db_prep_value(self, value): 
     if value is not None and not isinstance(value, PickledObject): 
      if type(value).__name__ in self.markable_types and not (isinstance(value, basestring) and len(value 
                             ) > MAX_MARKABLE_STRING_LENGTH): 
       value = unicode(self.generate_type_marked_value(value)) 
      else: 
       value = unicode(dbsafe_encode(value, self.compress)) 
     return value 

    def value_to_string(self, obj): 
     value = self._get_val_from_obj(obj) 
     return self.get_db_prep_value(value) 

    def get_internal_type(self): 
     return 'TextField' 

    def get_db_prep_lookup(self, lookup_type, value): 
     if lookup_type not in ['exact', 'in', 'isnull']: 
      raise TypeError('Lookup type %s is not supported.' % lookup_type) 
     return super(PickledObjectField, self).get_db_prep_lookup(lookup_type, value)