import re def get_insert_update(obj, key, obj_list, exclude_fields=None): """ :param obj: The object for compare :param key: a the key for compare to determine if we need to update or insert :param obj_list: list objects to compare :return: to_insert, _update """ db = {} to_insert = [] to_update = [] if key == 'pk': # the field pk doesn't exists so we change to id, because its the same key = 'id' if key in exclude_fields: raise Exception('The key "{}" should not be included in exclude_fields -> {}'.format(key, exclude_fields)) exclude_fields = exclude_fields or [] if 'pk' in exclude_fields: exclude_fields[exclude_fields.index('pk')] = 'id' # we change the field pk, because it doesn't exists exclude_fields_ids = ["{}_id".format(i) for i in exclude_fields] # dumping a db into memory for _obj in obj.objects.all(): if isinstance(key, list): # first check if is a list to create a custom key _key = _get_key(_obj, key) else: _key = _obj.__dict__[key] db[_key] = _obj # read local objects to determine if the record will be insert or update for _obj in obj_list: if isinstance(key, list): # first check if is a list to create a custom key _key = _get_key(_obj, key) else: _key = _obj.__dict__[key] if _key in db: # if the key is in db so we check if it esq obj_db = [(k, v) for k, v in db[_key].__dict__.items() if not re.match('^_.*', k) # excluding _state and k not in exclude_fields_ids and k not in exclude_fields] # excluding field and fields_id obj_tmp = [(k, v) for k, v in _obj.__dict__.items() if not re.match('^_.*', k) # not _state, _cache fields and k not in exclude_fields_ids and k not in exclude_fields] if obj_db != obj_tmp: to_update.append(_obj) # if the object has changed, we update it else: pass # if the object is equal, we didn't do it anything else: to_insert.append(_obj) # because we didn't found into the database, we create it return to_insert, to_update def _get_key(obj, lst): """ create a string key using multiples keys Example: obj.id -> 1, obj.name -> 'foo' lst['id', 'name'] :param lst: list of keys :return: 1_foo """ k = [] for t in lst: k.append(str(obj.__dict__[t])) return "_".split(k)