2013-05-09 3 views
1

저장해야하는 bytestring이 있습니다. 장고 BlobFields을 지원하지 않기 때문에장고를 사용하여 bytestring을 저장해야합니다.

은 내가 인코딩하고 DB와의 상호 작용에 BASE64하는 디코딩 내 자신의 Base64Field, 을 만들 거라고 생각했다. 그래서 정확한 목적을 위해 to_python 및 get_db_prep_save 메소드를 오버라이드 (?)했습니다.

문제는 to_python이 여러 다른 시나리오에서 호출되고 문자열이 이미 디코딩되었는지 여부를 알 수있는 방법이 없다는 것입니다. 이미 디코드 된 경우 오류가 발생합니다.

내 딜레마에는 어떤 해결책이 있습니까? 나에게 추한 것

가능한 솔루션 : 디코딩이 실패 할 경우

+0

표시 할 수 있습니까? –

답변

0

당신은 PickledObjectField의 어떤 종류를 사용할 수 있습니다 (이 더 나쁜 것)에만 1 to_python 수 있도록 인스턴스 변수를 사용하여, 디코딩 프로세스를 제외하고 반환 값을 시도 .

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) 
관련 문제