def __set__(self, instance, value): cls, subfield_type, normalize, lf_name, field_name, subfield_name, create_only = ( instance.__class__, self.subfield_type, self.normalize, self.subfield_name, self.field_name, self.subfield_name, self.create_only, ) json_field = getattr(instance, field_name) if normalize and value is not None: old = value value = normalize(value) if instance.status == Status.NEW and old != value: if instance.raw is None: instance.raw = {} instance.raw[lf_name] = old # value 를 subfield_type 으로 변환. 따라서 json_decode() 는 형변환도 구현해야 함 value = json_decode(value, subfield_type) # old old = json_field[subfield_name] if callable(old): old = None old = json_decode(old, subfield_type) if old != value: # TODO : if 블럭 밖에 있으면 에러 발생. 장고 내부 코드 확인 후 조처 ( django.db.models.query ) """ if annotation_col_map: for attr_name, col_pos in annotation_col_map.items(): setattr(obj, attr_name, row[col_pos]) """ if create_only: assert instance.status in (Status.CREATING, Status.NEW), console_log( "{}.{} = {} ({})".format( self.owner.__name__, self.subfield_name, value, instance.status)) assert old is None assert value is not None assert self.check_schema(value), console_log( "{}.check_schema({}) is fail!".format(self.subfield_name, value)) instance.assert_changeable(field_name) json_field[subfield_name] = json_encode(value) instance.onchange_subfield(field_name, subfield_name, old, value) return old
def __get__(self, instance, owner): if not instance: return self field_name, subfield_name, subfield_type, expire = ( self.field_name, self.subfield_name, self.subfield_type, self.expire, ) json_field = getattr(instance, field_name) value = json_field[subfield_name] if callable(value): try: value = value(instance) except Exception as e: msg = "{}: {}".format(e.__class__.__name__, str(e)) if "NoneType" in msg or "DoesNotExist" in msg: return None else: raise e assert not callable(value) assert self.check_schema(value) value = json_encode(value) json_field[subfield_name] = value value_decoded = json_decode(value, subfield_type) return value_decoded
def __set__(self, instance, patch): instance.assert_changeable(self.field_name) patch = json_decode(patch, list) assert self.check_schema(patch) patch = [json_encode(e) for e in patch] d = super().__get__(instance, instance.__class__) old = d[:] # address 가 바뀌면 안되기 때문에 성능을 약간 희생해서라도 이렇게 구현 d.clear() d.extend(patch) if old != d: instance.onchange_subfield(self.field_name, self.subfield_name, old, d) return old
def __set__(self, instance, patch): def encoder(d, k, v, storage): patch[k] = json_encode(v) instance.assert_changeable(self.field_name) cls, field_name, subfield_name = (instance.__class__, self.field_name, self.subfield_name) patch = json_decode(patch, dict) assert self.check_schema(patch) d = getattr(instance, field_name)[subfield_name] assert id(d) != id(patch) assert type(d) is dict old = {} old.update(d) json_walk(patch, encoder) d.update(patch) if old != d: instance.onchange_subfield(self.field_name, subfield_name, old, d) return old
def remove_index(self, index): encoded = self._d[index] del self._d[index] value = json_decode(encoded, self._element_type) return value
def __getitem__(self, key): encoded = self._d[key] # TODO : 튜닝 return json_decode(encoded, self._element_type)
def __getattr__(self, key): value = self._d[key] # TODO : 튜닝 return json_decode(value, self._subfield_type[key])
def on_create(self): super().on_create() for subfield_name, subfield in self.subfields["data"].items(): encoded = self.data[subfield_name] if encoded and not callable(encoded): self.onchange_subfield("data", subfield_name, None, json_decode(encoded, subfield.subfield_type))