Как поменять местами индексы постов?

У меня есть model с индексами order, например - 1, 2, 3, 5, 8, 10.... (пустые индексы якобы были удалены - 4, 6, 7, 9...)

Мне нужно получить индекс и поменять его местами с ближайшим индексом рядом с ним. (для перемещения вверх и вниз).

Что у меня есть:

def set_order_index(item: Posts, distinction: int):
    items_to_swap = Posts.objects.filter(
        order_index=item.order_index + distinction)
    if len(items_to_swap) > 0:
        item_to_swap = items_to_swap[0]
        item_to_swap.order_index = item.order_index
        item_to_swap.save()
    item.order_index += distinction
    item.save()

Для Up просмотров '+1':

def up_item(request, id):
    item = Posts.objects.get(id=id)
    set_order_index(item, +1)
    return redirect('index')

Для Down '-1'...

Но мой set_order_index делает только +1 и -1 всегда, а если получает одинаковое значение, то меняет местами. То есть если индекс 3, то set_order_index сделает только 4 (+1), но мне нужно поменять 3 на 5. Потому что нет индекса 4.

А если я использую Post с индексом 10 для Down - мне нужно поменяться с 8, но мои set_order_index делают только -1, и я получаю только 9. Но мне нужно 10, чтобы сразу поменять местами с 8.

В голове я понимаю, как это сделать через QuerySet, получив индексы всего, что есть > и <, а потом выбрать первый или последний - надо, соседний. Но в коде я не могу сделать так, чтобы это работало.

def swap_up(item):
    nextItem = Posts.objects.filter(order_index__gt=item.order_index).order_by('order_index').first()
    if nextItem:
        item_index = item.order_index
        item.order_index = nextItem.order_index
        nextItem.order_index = item_index

        item.save()
        nextItem.save()

def swap_down(item):
    prevItem = Posts.objects.filter(order_index__lt=item.order_index).order_by('order_index').last()
    if prevItem:
        item_index = item.order_index
        item.order_index = prevItem.order_index
        prevItem.order_index = item_index

        item.save()
        prevItem.save()
Вернуться на верх