diff -pruN 3.5-1/CHANGES.md 3.6-1/CHANGES.md
--- 3.5-1/CHANGES.md	2022-01-12 19:14:58.000000000 +0000
+++ 3.6-1/CHANGES.md	2022-05-30 14:01:39.000000000 +0000
@@ -1,6 +1,12 @@
 Change log
 ==========
 
+3.6 - 2022-05-30
+----------
+
+- Add `serializers.OrderedModelSerializer` to allow Django Rest Framework to re-order models (#251 #264)
+- Add tox builder for Django 4.0, drop building against 2.0 and 2.1 due to DRF compatibility.
+
 3.5 - 2022-01-12
 ----------------
 
diff -pruN 3.5-1/debian/changelog 3.6-1/debian/changelog
--- 3.5-1/debian/changelog	2022-01-18 10:34:17.000000000 +0000
+++ 3.6-1/debian/changelog	2022-08-01 20:48:03.000000000 +0000
@@ -1,3 +1,11 @@
+python-django-ordered-model (3.6-1) unstable; urgency=low
+
+  * New upstream release.
+  * Add python3-djangorestframework to Build-Depends, required by tests.
+  * Bump Standards-Version to 4.6.1.0.
+
+ -- Michael Fladischer <fladi@debian.org>  Mon, 01 Aug 2022 20:48:03 +0000
+
 python-django-ordered-model (3.5-1) unstable; urgency=low
 
   * New upstream release.
diff -pruN 3.5-1/debian/control 3.6-1/debian/control
--- 3.5-1/debian/control	2022-01-18 10:34:17.000000000 +0000
+++ 3.6-1/debian/control	2022-08-01 20:48:03.000000000 +0000
@@ -10,9 +10,10 @@ Build-Depends:
  python3-all,
  python3-babel,
  python3-django,
+ python3-djangorestframework,
  python3-setuptools,
  python3-six,
-Standards-Version: 4.6.0.1
+Standards-Version: 4.6.1.0
 Vcs-Browser: https://salsa.debian.org/python-team/packages/python-django-ordered-model
 Vcs-Git: https://salsa.debian.org/python-team/packages/python-django-ordered-model.git
 Homepage: https://github.com/bfirsh/django-ordered-model
diff -pruN 3.5-1/ordered_model/serializers.py 3.6-1/ordered_model/serializers.py
--- 3.5-1/ordered_model/serializers.py	1970-01-01 00:00:00.000000000 +0000
+++ 3.6-1/ordered_model/serializers.py	2022-05-30 14:01:39.000000000 +0000
@@ -0,0 +1,103 @@
+from rest_framework import serializers, fields
+
+
+class OrderedModelSerializer(serializers.ModelSerializer):
+    """
+    A ModelSerializer to provide a serializer that can be update and create
+    objects in a specific order.
+
+    Typically a `models.PositiveIntegerField` field called `order` is used to
+    store the order of the Model objects. This field can be customized by setting
+    the `order_field_name` attribute on the Model class.
+
+    This serializer will move the object to the correct
+    order if the ordering field is passed in the validated data.
+    """
+
+    def get_order_field(self):
+        """
+        Return the field name for the ordering field.
+
+        If inheriting from `OrderedModelBase`, the `order_field_name` attribute
+        must be set on the Model class. If inheriting from `OrderedModel`, the
+        `order_field_name` attribute is not required, as the `OrderedModel`
+        has the `order_field_name` attribute defaulting to 'order'.
+
+        Returns:
+            str: The field name for the ordering field.
+
+        Raises:
+            AttributeError: If the `order_field_name` attribute is not set,
+                either on the Model class or on the serializer's Meta class.
+        """
+
+        ModelClass = self.Meta.model  # pylint: disable=no-member,invalid-name
+        order_field_name = getattr(ModelClass, "order_field_name")
+
+        if not order_field_name:
+            raise AttributeError(
+                "The `order_field_name` attribute must be set to use the "
+                "OrderedModelSerializer. Either inherit from OrderedModel "
+                "(to use the default `order` field) or inherit from "
+                "`OrderedModelBase` and set the `order_field_name` attribute "
+                "on the " + ModelClass.__name__ + " Model class."
+            )
+
+        return order_field_name
+
+    def get_fields(self):
+        # make sure that DRF considers the ordering field writable
+        order_field = self.get_order_field()
+        d = super().get_fields()
+        for name, field in d.items():
+            if name == order_field:
+                if field.read_only:
+                    d[name] = fields.IntegerField()
+        return d
+
+    def update(self, instance, validated_data):
+        """
+        Update the instance.
+
+        If the `order_field_name` attribute is passed in the validated data,
+        the instance will be moved to the specified order.
+
+        Returns:
+            Model: The updated instance.
+        """
+
+        order = None
+        order_field = self.get_order_field()
+
+        if order_field in validated_data:
+            order = validated_data.pop(order_field)
+
+        instance = super().update(instance, validated_data)
+
+        if order is not None:
+            instance.to(order)
+
+        return instance
+
+    def create(self, validated_data):
+        """
+        Create a new instance.
+
+        If the `order_field_name` attribute is passed in the validated data,
+        the instance will be created at the specified order.
+
+        Returns:
+            Model: The created instance.
+        """
+        order = None
+        order_field = self.get_order_field()
+
+        if order_field in validated_data:
+            order = validated_data.pop(order_field)
+
+        instance = super().create(validated_data)
+
+        if order is not None:
+            instance.to(order)
+
+        return instance
diff -pruN 3.5-1/README.md 3.6-1/README.md
--- 3.5-1/README.md	2022-01-12 19:14:58.000000000 +0000
+++ 3.6-1/README.md	2022-05-30 14:01:39.000000000 +0000
@@ -29,6 +29,13 @@ Or if you have checked out the repositor
 $ python setup.py install
 ```
 
+Or to use the latest development code from our master branch:
+
+```bash
+$ pip uninstall django-ordered-model
+$ pip install git+git://github.com/django-ordered-model/django-ordered-model.git
+```
+
 Usage
 -----
 
@@ -46,6 +53,8 @@ class Item(OrderedModel):
 
 ```
 
+Then run the usual `$ ./manage.py makemigrations` and `$ ./manage.py migrate` to update your database schema.
+
 Model instances now have a set of methods to move them relative to each other.
 To demonstrate those methods we create two instances of `Item`:
 
@@ -224,7 +233,7 @@ class OpenQuestion(BaseQuestion):
 
 Custom Manager and QuerySet
 -----------------
-When your model your extends `OrderedModel`, it inherits a custom `ModelManager` instance, `OrderedModelManager`, which provides additional  operations on the resulting `QuerySet`. For example an `OrderedModel` subclass called `Item` that returns a queryset from `Item.objects.all()` supports the following functions:
+When your model your extends `OrderedModel`, it inherits a custom `ModelManager` instance which in turn provides additional operations on the resulting `QuerySet`. For example if `Item` is an `OrderedModel` subclass, the  queryset `Item.objects.all()` has functions:
 
 * `above_instance(object)`,
 * `below_instance(object)`,
@@ -233,18 +242,25 @@ When your model your extends `OrderedMod
 * `above(index)`,
 * `below(index)`
 
-If your model defines a custom `ModelManager` such as `ItemManager` below, you may wish to extend `OrderedModelManager` to retain those functions, as follows:
+If your `Model` uses a custom `ModelManager` (such as `ItemManager` below) please have it extend `OrderedModelManager`.
+
+If your `ModelManager` returns a custom `QuerySet` (such as `ItemQuerySet` below) please have it extend `OrderedModelQuerySet`.
 
 ```python
-from ordered_model.models import OrderedModelManager, OrderedModel
+from ordered_model.models import OrderedModel, OrderedModelManager, OrderedModelQuerySet
 
-class ItemManager(OrderedModelManager):
+class ItemQuerySet(OrderedModelQuerySet):
     pass
 
+class ItemManager(OrderedModelManager):
+    def get_queryset(self):
+        return ItemQuerySet(self.model, using=self._db)
+
 class Item(OrderedModel):
     objects = ItemManager()
 ```
 
+
 Custom ordering field
 ---------------------
 Extending `OrderedModel` creates a `models.PositiveIntegerField` field called `order` and the appropriate migrations. It customises the default `class Meta` to then order returned querysets by this field. If you wish to use an existing model field to store the ordering, subclass `OrderedModelBase` instead and set the attribute `order_field_name` to match your field name and the `ordering` attribute on `Meta`:
@@ -359,6 +375,29 @@ re-order one or more models.
     - `<model_name>`: Name of the model that's an OrderedModel.
 
 
+Django Rest Framework
+---------------------
+
+To support updating ordering fields by Django Rest Framework, we include a serializer `OrderedModelSerializer` that intercepts writes to the ordering field, and calls `OrderedModel.to()` method to effect a re-ordering:
+
+    from rest_framework import routers, serializers, viewsets
+    from ordered_model.serializers import OrderedModelSerializer
+    from tests.models import CustomItem
+
+    class ItemSerializer(serializers.HyperlinkedModelSerializer, OrderedModelSerializer):
+        class Meta:
+            model = CustomItem
+            fields = ['pkid', 'name', 'modified', 'order']
+
+    class ItemViewSet(viewsets.ModelViewSet):
+        queryset = CustomItem.objects.all()
+        serializer_class = ItemSerializer
+
+    router = routers.DefaultRouter()
+    router.register(r'items', ItemViewSet)
+
+Note that you need to include the 'order' field (or your custom field name) in the `Serializer`'s `fields` list, either explicitly or using `__all__`. See [ordered_model/serializers.py](ordered_model/serializers.py) for the implementation.
+
 Test suite
 ----------
 
@@ -378,16 +417,17 @@ $ tox
 Compatibility with Django and Python
 -----------------------------------------
 
-|django-ordered-model version | Django version      | Python version
-|-----------------------------|---------------------|--------------------
-| **3.5.x**                   | **3.x**, **4.x**    | **3.5** and above
-| **3.4.x**                   | **2.x**, **3.x**    | **3.5** and above
-| **3.3.x**                   | **2.x**             | **3.4** and above
-| **3.2.x**                   | **2.x**             | **3.4** and above
-| **3.1.x**                   | **2.x**             | **3.4** and above
-| **3.0.x**                   | **2.x**             | **3.4** and above
-| **2.1.x**                   | **1.x**             | **2.7** to **3.6**
-| **2.0.x**                   | **1.x**             | **2.7** to **3.6**
+|django-ordered-model version | Django version      | Python version    | DRF (optional)
+|-----------------------------|---------------------|-------------------|----------------
+| **3.6.x**                   | **3.x**, **4.x**    | **3.5** and above | 3.12 and above
+| **3.5.x**                   | **3.x**, **4.x**    | **3.5** and above | -
+| **3.4.x**                   | **2.x**, **3.x**    | **3.5** and above | -
+| **3.3.x**                   | **2.x**             | **3.4** and above | -
+| **3.2.x**                   | **2.x**             | **3.4** and above | -
+| **3.1.x**                   | **2.x**             | **3.4** and above | -
+| **3.0.x**                   | **2.x**             | **3.4** and above | -
+| **2.1.x**                   | **1.x**             | **2.7** to 3.6    | -
+| **2.0.x**                   | **1.x**             | **2.7** to 3.6    | -
 
 
 Maintainers
diff -pruN 3.5-1/setup.py 3.6-1/setup.py
--- 3.5-1/setup.py	2022-01-12 19:14:58.000000000 +0000
+++ 3.6-1/setup.py	2022-05-30 14:01:39.000000000 +0000
@@ -12,7 +12,7 @@ setup(
     name="django-ordered-model",
     long_description=long_description,
     long_description_content_type="text/markdown",
-    version="3.5",
+    version="3.6",
     description="Allows Django models to be ordered and provides a simple admin interface for reordering them.",
     author="Ben Firshman",
     author_email="ben@firshman.co.uk",
diff -pruN 3.5-1/tests/drf.py 3.6-1/tests/drf.py
--- 3.5-1/tests/drf.py	1970-01-01 00:00:00.000000000 +0000
+++ 3.6-1/tests/drf.py	2022-05-30 14:01:39.000000000 +0000
@@ -0,0 +1,44 @@
+from rest_framework import routers, serializers, viewsets
+from ordered_model.serializers import OrderedModelSerializer
+from tests.models import CustomItem, CustomOrderFieldModel
+
+
+class ItemSerializer(OrderedModelSerializer):
+    class Meta:
+        model = CustomItem
+        fields = "__all__"
+
+
+class ItemViewSet(viewsets.ModelViewSet):
+    queryset = CustomItem.objects.all()
+    serializer_class = ItemSerializer
+
+
+class CustomOrderFieldModelSerializer(OrderedModelSerializer):
+    class Meta:
+        model = CustomOrderFieldModel
+        fields = "__all__"
+
+
+class CustomOrderFieldModelViewSet(viewsets.ModelViewSet):
+    queryset = CustomOrderFieldModel.objects.all()
+    serializer_class = CustomOrderFieldModelSerializer
+
+
+class RenamedItemSerializer(OrderedModelSerializer):
+    renamedOrder = serializers.IntegerField(source="order")
+
+    class Meta:
+        model = CustomItem
+        fields = ("pkid", "name", "renamedOrder")
+
+
+class RenamedItemViewSet(viewsets.ModelViewSet):
+    queryset = CustomItem.objects.all()
+    serializer_class = RenamedItemSerializer
+
+
+router = routers.DefaultRouter()
+router.register(r"items", ItemViewSet)
+router.register(r"customorderfieldmodels", CustomOrderFieldModelViewSet)
+router.register(r"renameditems", RenamedItemViewSet, basename="renameditem")
diff -pruN 3.5-1/tests/settings.py 3.6-1/tests/settings.py
--- 3.5-1/tests/settings.py	2022-01-12 19:14:58.000000000 +0000
+++ 3.6-1/tests/settings.py	2022-05-30 14:01:39.000000000 +0000
@@ -11,6 +11,7 @@ INSTALLED_APPS = [
     "django.contrib.staticfiles",
     "django.contrib.sessions",
     "ordered_model",
+    "rest_framework",
     "tests",
 ]
 SECRET_KEY = "topsecret"
@@ -36,5 +37,6 @@ TEMPLATES = [
         },
     }
 ]
+REST_FRAMEWORK = {"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.AllowAny"]}
 STATIC_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "staticfiles")
 STATIC_URL = "/static/"
diff -pruN 3.5-1/tests/tests.py 3.6-1/tests/tests.py
--- 3.5-1/tests/tests.py	2022-01-12 19:14:58.000000000 +0000
+++ 3.6-1/tests/tests.py	2022-05-30 14:01:39.000000000 +0000
@@ -4,9 +4,14 @@ from io import StringIO
 from django.contrib.auth.models import User
 from django.core.management import call_command
 from django.utils.timezone import now
+from django.urls import reverse
 from django.test import TestCase
 from django import VERSION
 
+from rest_framework.test import APIRequestFactory, APITestCase
+from rest_framework import status
+from tests.drf import ItemViewSet, router
+
 from tests.models import (
     Answer,
     Item,
@@ -1125,3 +1130,84 @@ class ReorderModelTestCase(TestCase):
         self.assertEqual(
             "changing order of tests.OpenQuestion (4) from 3 to 2\n", out.getvalue()
         )
+
+
+class DRFTestCase(APITestCase):
+    fixtures = ["test_items.json"]
+
+    def setUp(self):
+        self.item1 = CustomItem.objects.create(pkid="a", name="1")
+        self.item2 = CustomItem.objects.create(pkid="b", name="2")
+
+    def test_create_shuffles_down(self):
+        data = {"name": "3", "pkid": "c", "order": "0"}
+        response = self.client.post(reverse("customitem-list"), data, format="json")
+        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        self.assertEqual(CustomItem.objects.count(), 3)
+        self.assertEqual(
+            response.data, {"pkid": "c", "name": "3", "modified": None, "order": 0}
+        )
+        self.assertEqual(CustomItem.objects.get(pkid="a").order, 1)
+        self.assertEqual(CustomItem.objects.get(pkid="b").order, 2)
+
+        # check DRF exposes the modified value
+        response = self.client.get(
+            reverse("customitem-detail", kwargs={"pk": "b"}), {}, format="json"
+        )
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(
+            response.data, {"pkid": "b", "name": "2", "modified": None, "order": 2}
+        )
+
+    def test_patch_shuffles_down(self):
+        self.item3 = CustomItem.objects.create(pkid="c", name="3")
+
+        # re-order an item
+        response = self.client.patch(
+            reverse("customitem-detail", kwargs={"pk": "b"}),
+            {"order": 2, "name": "x"},
+            format="json",
+        )
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(
+            response.data, {"pkid": "b", "name": "x", "modified": None, "order": 2}
+        )
+        self.assertEqual(CustomItem.objects.count(), 3)
+        self.assertEqual(CustomItem.objects.get(pkid="a").order, 0)
+        self.assertEqual(CustomItem.objects.get(pkid="c").order, 1)
+        self.assertEqual(CustomItem.objects.get(pkid="b").order, 2)
+
+    def test_custom_order_field_model(self):
+        response = self.client.get(
+            reverse("customorderfieldmodel-detail", kwargs={"pk": 1}), {}, format="json"
+        )
+        self.assertEqual(response.data, {"id": 1, "name": "1", "sort_order": 0})
+        # re-order a lower item to top
+        response = self.client.patch(
+            reverse("customorderfieldmodel-detail", kwargs={"pk": 2}),
+            {"sort_order": 0},
+            format="json",
+        )
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data, {"id": 2, "name": "2", "sort_order": 0})
+        # check old first item is pushed down
+        response = self.client.get(
+            reverse("customorderfieldmodel-detail", kwargs={"pk": 1}), {}, format="json"
+        )
+        self.assertEqual(response.data, {"id": 1, "name": "1", "sort_order": 1})
+
+    def test_serializer_renames_order_field(self):
+        response = self.client.get(
+            reverse("renameditem-detail", kwargs={"pk": "b"}), {}, format="json"
+        )
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(response.data, {"pkid": "b", "name": "2", "renamedOrder": 1})
+        # move b to top
+        response = self.client.patch(
+            reverse("renameditem-detail", kwargs={"pk": "b"}),
+            {"renamedOrder": 0},
+            format="json",
+        )
+        self.assertEqual(response.data, {"pkid": "b", "name": "2", "renamedOrder": 0})
+        self.assertEqual(CustomItem.objects.get(pkid="b").order, 0)
+        self.assertEqual(CustomItem.objects.get(pkid="a").order, 1)
diff -pruN 3.5-1/tests/urls.py 3.6-1/tests/urls.py
--- 3.5-1/tests/urls.py	2022-01-12 19:14:58.000000000 +0000
+++ 3.6-1/tests/urls.py	2022-05-30 14:01:39.000000000 +0000
@@ -1,7 +1,9 @@
-from django.urls import path
+from django.urls import path, include
 from django.contrib import admin
 
+from tests.drf import router
+
 admin.autodiscover()
 admin.site.enable_nav_sidebar = False
 
-urlpatterns = [path("admin/", admin.site.urls)]
+urlpatterns = [path("admin/", admin.site.urls), path("api/", include(router.urls))]
diff -pruN 3.5-1/tox.ini 3.6-1/tox.ini
--- 3.5-1/tox.ini	2022-01-12 19:14:58.000000000 +0000
+++ 3.6-1/tox.ini	2022-05-30 14:01:39.000000000 +0000
@@ -1,12 +1,12 @@
 [tox]
 envlist =
-    py{34,35,36,37}-django20
-    py{35,36,37}-django21
     py{35,36,37,38,39}-django22
     py{36,37,38,39}-django30
     py{36,37,38,39}-django31
     py{36,37,38,39}-django32
+    py{38,39}-django40
     py{38,39}-djangoupstream
+    py{38,39}-drfupstream
     black
 
 [gh-actions]
@@ -20,13 +20,18 @@ python =
 
 [testenv]
 deps =
-    django20: Django~=2.0.0
-    django21: Django~=2.1.0
     django22: Django~=2.2.17
     django30: Django~=3.0.11
     django31: Django~=3.1.3
     django32: Django~=3.2.0
+    django40: Django~=4.0.0
     djangoupstream: https://github.com/django/django/archive/main.tar.gz
+
+    drfupstream: Django~=3.2.0
+    drfupstream: https://github.com/encode/django-rest-framework/archive/master.tar.gz
+    django22: djangorestframework~=3.12.0
+    django30,django31,django32: djangorestframework~=3.12.0
+    django40,djangoupstream: djangorestframework~=3.13.0
     coverage
 commands =
     coverage run {envbindir}/django-admin test --pythonpath=. --settings=tests.settings {posargs}
