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)