2013-05-09 58 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) 
相關問題