diff --git a/client/src/pages/presentationEditor/PresentationEditorPage.tsx b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
index 75652bed40a40b22e67755b3e0502e173ec2e999..d84944b47440997de210a258c65a6316caab63e9 100644
--- a/client/src/pages/presentationEditor/PresentationEditorPage.tsx
+++ b/client/src/pages/presentationEditor/PresentationEditorPage.tsx
@@ -10,6 +10,7 @@ import { getCities } from '../../actions/cities'
 import { getEditorCompetition, setEditorSlideId, setEditorViewId } from '../../actions/editor'
 import { getTypes } from '../../actions/typesAction'
 import { useAppDispatch, useAppSelector } from '../../hooks'
+import { RichSlide } from '../../interfaces/ApiRichModels'
 import { renderSlideIcon } from '../../utils/renderSlideIcon'
 import { RemoveMenuItem } from '../admin/styledComp'
 import { Content, InnerContent } from '../views/styled'
@@ -50,6 +51,7 @@ interface CompetitionParams {
 const PresentationEditorPage: React.FC = () => {
   const { competitionId }: CompetitionParams = useParams()
   const dispatch = useAppDispatch()
+  const [sortedSlides, setSortedSlides] = useState<RichSlide[]>([])
   const activeSlideId = useAppSelector((state) => state.editor.activeSlideId)
   const activeViewTypeId = useAppSelector((state) => state.editor.activeViewTypeId)
   const competition = useAppSelector((state) => state.editor.competition)
@@ -60,6 +62,10 @@ const PresentationEditorPage: React.FC = () => {
     dispatch(getCities())
   }, [])
 
+  useEffect(() => {
+    setSortedSlides(competition.slides.sort((a, b) => (a.order > b.order ? 1 : -1)))
+  }, [competition])
+
   const setActiveSlideId = (id: number) => {
     dispatch(setEditorSlideId(id))
   }
@@ -111,16 +117,19 @@ const PresentationEditorPage: React.FC = () => {
   }
 
   const onDragEnd = async (result: DropResult) => {
-    // dropped outside the list
-    if (!result.destination) {
+    // dropped outside the list or same place
+    if (!result.destination || result.destination.index === result.source.index) {
       return
     }
     const draggedIndex = result.source.index
-    const draggedSlideId = competition.slides.find((slide) => slide.order === draggedIndex)?.id
+    const draggedSlideId = sortedSlides[draggedIndex].id
+    const slidesCopy = [...sortedSlides]
+    const [removed] = slidesCopy.splice(draggedIndex, 1)
+    slidesCopy.splice(result.destination.index, 0, removed)
+    setSortedSlides(slidesCopy)
     if (draggedSlideId) {
       await axios
         .put(`/api/competitions/${competitionId}/slides/${draggedSlideId}/order`, { order: result.destination.index })
-        .then(() => dispatch(getEditorCompetition(competitionId)))
         .catch(console.log)
     }
   }
@@ -161,26 +170,26 @@ const PresentationEditorPage: React.FC = () => {
             <DragDropContext onDragEnd={onDragEnd}>
               <Droppable droppableId="droppable">
                 {(provided) => (
-                  <div key={provided.innerRef.toString()} ref={provided.innerRef} {...provided.droppableProps}>
-                    {competition.slides &&
-                      competition.slides.map((slide, index) => (
-                        <Draggable key={slide.order} draggableId={slide.id.toString()} index={index}>
-                          {(provided, snapshot) => (
-                            <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
-                              <SlideListItem
-                                divider
-                                button
-                                selected={slide.id === activeSlideId}
-                                onClick={() => setActiveSlideId(slide.id)}
-                                onContextMenu={(event) => handleRightClick(event, slide.id)}
-                              >
-                                {renderSlideIcon(slide)}
-                                <ListItemText primary={`Sida ${slide.order + 1}`} />
-                              </SlideListItem>
-                            </div>
-                          )}
-                        </Draggable>
-                      ))}
+                  <div ref={provided.innerRef} {...provided.droppableProps}>
+                    {sortedSlides.map((slide, index) => (
+                      <Draggable key={slide.id} draggableId={slide.id.toString()} index={index}>
+                        {(provided, snapshot) => (
+                          <div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
+                            <SlideListItem
+                              divider
+                              key={slide.order}
+                              button
+                              selected={slide.id === activeSlideId}
+                              onClick={() => setActiveSlideId(slide.id)}
+                              onContextMenu={(event) => handleRightClick(event, slide.id)}
+                            >
+                              {renderSlideIcon(slide)}
+                              <ListItemText primary={`Sida ${slide.id}`} />
+                            </SlideListItem>
+                          </div>
+                        )}
+                      </Draggable>
+                    ))}
                     {provided.placeholder}
                   </div>
                 )}
diff --git a/server/app/apis/slides.py b/server/app/apis/slides.py
index ee9689b51ad13a95941b7b9033ec3556d33f74b6..7f322d5231f063eecd287248928d85f945469a25 100644
--- a/server/app/apis/slides.py
+++ b/server/app/apis/slides.py
@@ -8,7 +8,10 @@ import app.database.controller as dbc
 from app.apis import item_response, list_response, protect_route
 from app.core.dto import SlideDTO
 from app.core.parsers import sentinel
+from app.database.controller.get import slide_count
+from app.database.models import Competition
 from flask_restx import Resource, reqparse
+from flask_restx.errors import abort
 
 api = SlideDTO.api
 schema = SlideDTO.schema
@@ -78,26 +81,18 @@ class SlideOrder(Resource):
         """ Edits the specified slide order using the provided arguments. """
 
         args = slide_parser_edit.parse_args(strict=True)
-        order = args.get("order")
+        new_order = args.get("order")
 
         item_slide = dbc.get.slide(competition_id, slide_id)
 
-        if order == item_slide.order:
+        if new_order == item_slide.order:
             return item_response(schema.dump(item_slide))
 
-        # clamp order between 0 and max
-        order_count = dbc.get.slide_count(competition_id)
-        if order < 0:
-            order = 0
-        elif order >= order_count - 1:
-            order = order_count - 1
-
-        # get slide at the requested order
-        item_slide_id = dbc.get.slide(competition_id, order)
-
-        # switch place between them
-        item_slide = dbc.edit.switch_order(item_slide, item_slide_id)
+        if not (0 <= new_order < dbc.get.slide_count(competition_id)):
+            abort(codes.BAD_REQUEST, f"Cant change to invalid slide order '{new_order}'")
 
+        item_competition = dbc.get.one(Competition, competition_id)
+        dbc.utils.move_slides(item_competition, item_slide.order, new_order)
         return item_response(schema.dump(item_slide))
 
 
diff --git a/server/app/database/controller/utils.py b/server/app/database/controller/utils.py
index f27ce32bae1429ec606f1b895535f3e0aea74d50..9662b08ea2e2a443955da07d07b0681bf88de0f8 100644
--- a/server/app/database/controller/utils.py
+++ b/server/app/database/controller/utils.py
@@ -9,25 +9,70 @@ from app.database.models import Code
 from flask_restx import abort
 
 
-def move_slides(item_competition, start_order, end_order):
-    """ Changes a slide order and then arranges other affected slides. """
+def move_slides(item_competition, from_order, to_order):
+    """
+    Move slide from from_order to to_order in item_competition.
+    """
+
+    num_slides = len(item_competition.slides)
+    assert 0 <= from_order < num_slides, "Invalid order to move from"
+    assert 0 <= to_order < num_slides, "Invalid order to move to"
+
+    # This function is sooo terrible, someone please tell me how to update
+    # multiple values in the database at the same time with unique constraints.
+    # If you update all the values at the same time none of them will collide
+    # but that database doesn't know that so you have to update them to some
+    # other value before and then change every value back to the correct one,
+    # so 2 commits.
+
+    # An example will follow the entire code to make it clear what it does
+    # Lets say we have 5 slides, and we want to move the slide at index 1
+    # to index 4.
+    # We begin with a list of slides with orders [0, 1, 2, 3, 4]
 
     slides = item_competition.slides
-    # Move up
-    if start_order < end_order:
-        for i in range(start_order + 1, end_order):
-            slides[i].order -= 1
 
-    # Move down
-    elif start_order > end_order:
-        for i in range(end_order, start_order):
-            slides[i].order += 1
+    change = 1 if to_order < from_order else -1
+    start_order = min(from_order, to_order)
+    end_order = max(from_order, to_order)
 
-    # start = 5, end = 1
-    # 1->2, 2->3, 4->5
-    # 5 = 1
+    # Move slides up 100
+    for item_slide in slides:
+        item_slide.order += 100
+
+    # Our slide orders now look like [100, 101, 102, 103, 104]
+
+    # Move slides between from and to order either up or down, but minus in front
+    for item_slide in slides:
+        if start_order <= item_slide.order - 100 <= end_order:
+            item_slide.order = -(item_slide.order + change)
+
+    # Our slide orders now look like [100, -100, -101, -102, -103]
+
+    # Find the slide that was to be moved and change it to correct order with minus in front
+    for item_slide in slides:
+        if item_slide.order == -(from_order + change + 100):
+            item_slide.order = -(to_order + 100)
+            break
+
+    # Our slide orders now look like [100, -104, -101, -102, -103]
+
+    db.session.commit()
+
+    # Negate all order so that they become positive
+    for item_slide in slides:
+        if start_order <= -(item_slide.order + 100) <= end_order:
+            item_slide.order = -(item_slide.order)
+
+    # Our slide orders now look like [100, 104, 101, 102, 103]
+
+    for item_slide in slides:
+        item_slide.order -= 100
+
+    # Our slide orders now look like [0, 4, 1, 2, 3]
+
+    # We have now successfully moved slide 1 to 4
 
-    slides[start_order].order = end_order
     return commit_and_refresh(item_competition)
 
 
diff --git a/server/tests/test_db.py b/server/tests/test_db.py
index c504ed14ff39224f9bb76fe8fd32ca99e12dd725..568c1c479fdf6f1edaaabf6765171613ae4faeb5 100644
--- a/server/tests/test_db.py
+++ b/server/tests/test_db.py
@@ -3,10 +3,10 @@ This file tests the database controller functions.
 """
 
 import app.database.controller as dbc
-from app.database.models import City, Competition, Media, MediaType, Role, User, Code
+from app.database.models import City, Code, Competition, Media, MediaType, Role, User
 
 from tests import app, client, db
-from tests.test_helpers import add_default_values, assert_exists, assert_insert_fail, delete
+from tests.test_helpers import add_default_values, assert_exists, assert_insert_fail, assert_slide_order, delete
 
 
 def test_user(client):
@@ -151,6 +151,33 @@ def check_slides_copy(item_slide_original, item_slide_copy, num_slides, order):
     assert item_slide_copy == item_slides[order]
 
 
+def test_move_slides(client):
+    add_default_values()
+
+    item_comp = dbc.get.one(Competition, 1)
+
+    for _ in range(9):
+        dbc.add.slide(item_comp.id)
+
+    # Move from beginning to end
+    item_comp = dbc.utils.move_slides(item_comp, 0, 9)
+    assert_slide_order(item_comp, [9, 0, 1, 2, 3, 4, 5, 6, 7, 8])
+
+    # Move from end to beginning
+    item_comp = dbc.utils.move_slides(item_comp, 9, 0)
+    assert_slide_order(item_comp, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+
+    # Move some things in the middle
+    item_comp = dbc.utils.move_slides(item_comp, 3, 7)
+    assert_slide_order(item_comp, [0, 1, 2, 7, 3, 4, 5, 6, 8, 9])
+
+    item_comp = dbc.utils.move_slides(item_comp, 1, 5)
+    assert_slide_order(item_comp, [0, 5, 1, 7, 2, 3, 4, 6, 8, 9])
+
+    item_comp = dbc.utils.move_slides(item_comp, 8, 2)
+    assert_slide_order(item_comp, [0, 6, 1, 8, 3, 4, 5, 7, 2, 9])
+
+
 """
 def test_question(client):
     add_default_values()
diff --git a/server/tests/test_helpers.py b/server/tests/test_helpers.py
index 85c1f114a8c01da6e7d5370bffe2ccb9ea8aed1c..7d5625385f01f81cc326bca9d5114322ad5f52e0 100644
--- a/server/tests/test_helpers.py
+++ b/server/tests/test_helpers.py
@@ -153,3 +153,11 @@ def change_order_test(client, cid, slide_id, new_slide_id, h):
     # Changes order
     response, _ = put(client, f"/api/competitions/{cid}/slides/{slide_id}/order", {"order": new_order}, headers=h)
     assert response.status_code == codes.OK
+
+
+def assert_slide_order(item_comp, correct_order):
+    """
+    Assert that the slides in the given competition are in the correct order
+    """
+    for slide, order in zip(item_comp.slides, correct_order):
+        assert slide.order == order