2013-05-09 23 views
1

我有一个需要存储的字节串。需要使用Django存储字节串

由于Django不支持BlobFields我以为我会创建自己的Base64Field, ,编码并解码base64与db的交互。 所以我重写(?)to_python和get_db_prep_save方法来达到这个确切目的。

问题在于,to_python在各种不同的场景中被调用,不仅仅是一次,而且 也无法确定字符串是否已经被解码。如果它已被解码,则显然会发生错误 。

我的困境有什么解决方案?

似乎难看我

可能的解决方案:尝试不同的解码过程中,返回值,如果解码失败,用一个实例变量只允许1个to_python(这似乎更糟)

+0

您可以显示方法吗? – 2013-05-09 08:57:44

回答

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) 
相关问题