def save(self, obj): if not self.polymorphic_fields['polymorphic_type_id'].get_value(obj): obj.polymorphic_type_id = mapper_registry[obj.__class__].name for base in self.polymorphic_bases: new_record = self.is_new(obj) base.save(obj) for key, base_key in zip(to_tuple(self.pk), to_tuple(base.pk)): self.fields[key].set_value(obj, self.polymorphic_fields[base_key].get_value(obj)) self.is_new(obj, new_record) return super(PolymorphicMapper, self).save(obj)
def __init__(self, type_field="object_type_id", rel_field=None, field=None, on_delete=cascade, rel_name=None, rel_query=None): self._cache = SpecialMappingAccessor(SpecialAttrAccessor('cache', default=dict)) self._type_field = type_field if not rel_field or isinstance(rel_field, collections.Callable): self._rel_field = rel_field else: self._rel_field = to_tuple(rel_field) self._field = field and to_tuple(field) self.on_delete = on_delete self._rel_name = rel_name self._rel_query = rel_query
def get(self, _obj_pk=None, **kwargs): if _obj_pk is not None: identity_map = IdentityMap(self._using) key = self.make_identity_key(self.model, _obj_pk) if identity_map.exists(key): return identity_map.get(key) try: obj = self.get(**{k: v for k, v in zip(to_tuple(self.pk), to_tuple(_obj_pk))}) except ObjectDoesNotExist: identity_map.add(key) raise else: # obj added to identity_map by loader (self.load()) return obj if kwargs: q = self.query for k, v in kwargs.items(): q = q.where(self.sql_table.get_field(k) == v) return q[0]
def _get_objects(self, models, rows): objs = [] for model, model_row in zip(models, rows): mapper = mapper_registry[model] pk = to_tuple(mapper.pk) pk_columns = tuple(mapper.fields[k].columns for k in pk) model_row_dict = dict(model_row) pk_values = tuple(model_row_dict[k] for k in pk_columns) key = (model, pk_values) if key not in self._state: self._state[key] = mapper.load(model_row, from_db=True) objs.append(self._state[key]) return objs
def get(self, instance): val = self.get_value(instance) if not all(val): return None cached_obj = self._get_cache(instance, self.name) if not isinstance(cached_obj, self.rel_model) or self.get_rel_value(cached_obj) != val: if self._rel_query is None and self.rel_field == to_tuple(mapper_registry[self.rel_model].pk): obj = mapper_registry[self.rel_model].get(val) # to use IdentityMap else: obj = self.rel_query.where(self.get_rel_where(instance))[0] self._set_cache(instance, self.name, obj) return instance._cache[self.name]
def compute(self): if self._from_db: data_mapped = self._map_data_from_db(self._data) else: data_mapped = dict(self._data) identity_map = IdentityMap(self._mapper.using()) key = self._mapper.make_identity_key(self._mapper.model, tuple(data_mapped[i] for i in to_tuple(self._mapper.pk))) try: obj = identity_map.get(key) except KeyError: # First loading obj = self._do_load(data_mapped) except ObjectDoesNotExist: # Serializable transaction level raise else: if reload: self._do_reload(obj, data_mapped) else: return obj self._mapper.original_data(obj, data_mapped) self._mapper.is_new(obj, False) identity_map.add(key, obj) return obj
def set_pk(self, obj, value): for k, v in zip(to_tuple(self.pk), to_tuple(value)): self.fields[k].set_value(obj, v)
def _insert(self, obj): cursor = databases[self._using].execute(self._insert_query(obj)) if not all(to_tuple(self.get_pk(obj))): self.set_pk(obj, self.base_query.result.db.last_insert_id(cursor)) IdentityMap(self._using).add(self.make_identity_key(self.model, self.get_pk(obj)))
def _insert_query(self, obj): auto_pk = not all(to_tuple(self.get_pk(obj))) data = self.unload(obj, exclude=(to_tuple(self.pk) if auto_pk else ()), to_db=True) return smartsql.Insert(table=self.sql_table, map=data)
def make_identity_key(model, pk): return (model, to_tuple(pk))
def _make_tree_path(self, obj): tree_path = self.KEY_SEPARATOR.join(self._mp_encode(i).zfill(self.PATH_DIGITS) for i in to_tuple(self.get_pk(obj))) if obj.parent: tree_path = self.PATH_SEPARATOR.join((obj.parent.tree_path, tree_path)) tree_path += self.PATH_SEPARATOR return tree_path
def _do_prepare_model(self, model): setattr(model, 'parent', RelationDescriptor(ForeignKey( 'self', field=tuple('parent_{}'.format(k) for k in to_tuple(self.pk)), rel_name="children" )))
def rel_field(self): if isinstance(self._rel_field, collections.Callable): return to_tuple(self._rel_field(self)) return self._rel_field