diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 47b7d774ac8d35c87fb5c6ceeba8dbf2b4c8b048..c7bf2ec8fded0f83ebbf68986122818f10c74453 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -21,7 +21,7 @@ coverage:
   extends: .test
   variables:
     TOX_ENVLIST: coverage
-    PYTHON_VERSION: "3.7"
+    PYTHON_VERSION: "3.9"
 
   # Look for the summary line output from coverage's text report. The
   # parentheses are used to indicate which portion of the report contains the
@@ -33,7 +33,7 @@ flake8:
   extends: .test
   variables:
     TOX_ENVLIST: flake8
-    PYTHON_VERSION: "3.7"
+    PYTHON_VERSION: "3.9"
 
 # Run test suite against supported Python/Django combinations.
 python36-django22:
@@ -72,18 +72,6 @@ python39-django32:
     TOX_DJANGO_FRAGMENT: "django32"
 
 # Template jobs which run tests in various Python versions.
-.py34:
-  extends: .test
-  variables:
-    PYTHON_VERSION: "3.4"
-    TOX_PY_FRAGMENT: "py34"
-
-.py35:
-  extends: .test
-  variables:
-    PYTHON_VERSION: "3.5"
-    TOX_PY_FRAGMENT: "py35"
-
 .py36:
   extends: .test
   variables:
diff --git a/setup.py b/setup.py
index 6518737724193348548b44df20f51be4f4a1580d..fcf69b442157e98550f832b168b8797d3fdf0c6e 100755
--- a/setup.py
+++ b/setup.py
@@ -13,7 +13,7 @@ setup(
     author_email='devops@uis.cam.ac.uk',
     packages=find_packages(),
     include_package_data=True,
-    install_requires=['django>=1.11', 'ibisclient~=1.3'],
+    install_requires=['django>=2.2', 'ibisclient~=1.3'],
     classifiers=[
         'Development Status :: 5 - Production/Stable',
         'Environment :: Web Environment',
diff --git a/tox.ini b/tox.ini
index ab9e6498b9f144567ab19b0b855868f025029c67..2c13d9606b9e121c4543b3e5ea082552092b68ef 100644
--- a/tox.ini
+++ b/tox.ini
@@ -38,9 +38,7 @@ deps=
     .
     mock
     coverage
-    django111: Django>=1.11,<2.0
-    django20: Django>=2.0,<2.1
-    django21: Django>=2.1,<2.2
+    django22: Django>=2.2,<3.0
     django32: Django>=3.2,<3.3
 # Specify the default environment.
 commands=