Repository: torchbox/wagtail-storages (language: python)

Issue:
Django 5.1: ImportError: cannot import name 'get_storage_class' from 'django.core.files.storage' 
When I tried to use `django-storages` with Django 5.1 I have got following error:

```
Traceback (most recent call last):
  File "/home/petr/soubory/programovani/blenderkit/blenderhub_server/manage.py", line 28, in <module>
    execute_from_command_line(sys.argv)
  File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/django/core/management/__init__.py", line 416, in execute
    django.setup()
  File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/django/apps/registry.py", line 124, in populate
    app_config.ready()
  File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/wagtail_storages/apps.py", line 10, in ready
    from wagtail_storages import signal_handlers
  File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/wagtail_storages/signal_handlers.py", line 9, in <module>
    from wagtail_storages.utils import (
  File "/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/wagtail_storages/utils.py", line 4, in <module>
    from django.core.files.storage import get_storage_class
ImportError: cannot import name 'get_storage_class' from 'django.core.files.storage' (/home/petr/.cache/pypoetry/virtualenvs/blenderkit-server-eqrfB9dY-py3.11/lib/python3.11/site-packages/django/core/files/storage/__init__.py
```


Discussion / hints:

Fix patch:
diff --git a/tox.ini b/tox.ini
index 56dbf87..5a12fa2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,8 @@
 [tox]
 envlist =
-    py{38,39,310,311}-dj42-wagtail{52,60,61}
-    py{310,311,312}-dj50-wagtail{52,60,61}
+    py{38,39,310,311}-dj42-wagtail{52,61,62}
+    py{311,312}-dj{50}-wagtail{52,61,62}
+    py{311,312}-dj{51}-wagtail{61,62}
     flake8
     isort
     black
@@ -21,9 +22,11 @@ setenv =
 deps =
     dj42: Django>=4.2,<4.3
     dj50: Django>=5.0,<5.1
+    dj51: Django>=5.1,<5.2
     wagtail52: wagtail>=5.2,<5.3
     wagtail60: wagtail>=6.0,<6.1
     wagtail61: wagtail>=6.1,<6.2
+    wagtail62: wagtail>=6.2,<6.3
     wagtailmain: git+https://github.com/wagtail/wagtail.git@main#egg=Wagtail
 
 install_command = pip install -U {opts} {packages}
diff --git a/wagtail_storages/utils.py b/wagtail_storages/utils.py
index ad19ec7..1eba6b3 100644
--- a/wagtail_storages/utils.py
+++ b/wagtail_storages/utils.py
@@ -1,7 +1,7 @@
 import logging
 
 from django.conf import settings
-from django.core.files.storage import get_storage_class
+from django.core.files.storage import default_storage
 
 from wagtail.contrib.frontend_cache.utils import PurgeBatch
 from wagtail.documents import get_document_model
@@ -47,7 +47,7 @@ def build_absolute_urls_for_all_sites_for_path(path):
 
 def is_s3_boto3_storage_used():
     return issubclass(
-        get_storage_class(),
+        default_storage.__class__,
         storages.backends.s3boto3.S3Boto3Storage,
     )
 


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 29738c9..fdbdbe7 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -34,6 +34,7 @@ jobs:
       max-parallel: 4
       matrix:
         python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
+      fail-fast: false
 
     steps:
       - uses: actions/checkout@v4
diff --git a/wagtail_storages/tests/test_backends.py b/wagtail_storages/tests/test_backends.py
index e129be2..ccd8e49 100644
--- a/wagtail_storages/tests/test_backends.py
+++ b/wagtail_storages/tests/test_backends.py
@@ -1,4 +1,4 @@
-from django.core.files.storage import get_storage_class
+from django.core.files.storage import default_storage
 from django.test import TestCase
 
 from storages.backends.s3boto3 import S3Boto3Storage
@@ -18,7 +18,7 @@ def test_returns_s3_boto_subclass(self):
     def test_backend_overrides_settings(self):
         private_backend = self.backend_class()
 
-        default_backend = get_storage_class()()
+        default_backend = default_storage.__class__()
         self.assertIsInstance(default_backend, S3Boto3Storage)
 
         # Make sure querystring authentication is enabled and custom domain is
diff --git a/wagtail_storages/tests/test_management_commands.py b/wagtail_storages/tests/test_management_commands.py
index 0cc660c..bcf0b56 100644
--- a/wagtail_storages/tests/test_management_commands.py
+++ b/wagtail_storages/tests/test_management_commands.py
@@ -8,7 +8,7 @@ def test_call_does_not_fail(self):
         call_command("fix_document_acls")
 
     @override_settings(
-        DEFAULT_FILE_STORAGE="django.core.files.storage.FileSystemStorage"
+        STORAGES={"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"}}
     )
     def test_call_fails_when_s3_boto3_storage_not_used(self):
         with self.assertRaisesRegex(
diff --git a/wagtail_storages/tests/test_signal_handlers.py b/wagtail_storages/tests/test_signal_handlers.py
index 1343dcb..04801c9 100644
--- a/wagtail_storages/tests/test_signal_handlers.py
+++ b/wagtail_storages/tests/test_signal_handlers.py
@@ -26,7 +26,7 @@
 
 class TestDecorators(TestCase):
     @override_settings(
-        DEFAULT_FILE_STORAGE="django.core.files.storage.FileSystemStorage"
+        STORAGES={"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"}}
     )
     def test_skipping_s3_storage_decorator_with_non_s3_storage(self):
         mock = MagicMock()
@@ -101,7 +101,7 @@ def test_cache_purged_for_private_collection(self):
         private_collection = CollectionViewRestrictionFactory().collection
         DocumentFactory(collection=private_collection)
         with mock.patch(
-            "wagtail.contrib.frontend_cache.backends.urlopen"
+            "wagtail.contrib.frontend_cache.backends.http.urlopen"
         ) as urlopen_mock:
             purge_documents_when_collection_saved_with_restrictions(
                 sender=private_collection._meta.model, instance=private_collection
@@ -127,7 +127,7 @@ def test_cache_not_purged_for_public_collection(self):
         collection = CollectionFactory()
         DocumentFactory.create_batch(10, collection=collection)
         with mock.patch(
-            "wagtail.contrib.frontend_cache.backends.urlopen"
+            "wagtail.contrib.frontend_cache.backends.http.urlopen"
         ) as urlopen_mock:
             purge_documents_when_collection_saved_with_restrictions(
                 sender=collection._meta.model, instance=collection
@@ -155,7 +155,7 @@ class TestPurgeDocumentFromCacheWhenSaved(CreateBucket, TestCase):
     def test_create_new_document_purges_cache_for_that_url(self):
         document = DocumentFactory()
         with mock.patch(
-            "wagtail.contrib.frontend_cache.backends.urlopen"
+            "wagtail.contrib.frontend_cache.backends.http.urlopen"
         ) as urlopen_mock:
             purge_document_from_cache_when_saved(
                 sender=document._meta.model, instance=document
@@ -180,7 +180,7 @@ def test_create_new_document_purges_cache_for_that_url(self):
     def test_delete_document_purges_cache_for_that_url(self):
         document = DocumentFactory()
         with mock.patch(
-            "wagtail.contrib.frontend_cache.backends.urlopen"
+            "wagtail.contrib.frontend_cache.backends.http.urlopen"
         ) as urlopen_mock:
             purge_document_from_cache_when_deleted(
                 sender=document._meta.model, instance=document
diff --git a/wagtail_storages/tests/test_utils.py b/wagtail_storages/tests/test_utils.py
index 7903493..9a0fd2b 100644
--- a/wagtail_storages/tests/test_utils.py
+++ b/wagtail_storages/tests/test_utils.py
@@ -13,12 +13,14 @@
 
 class TestIsS3Boto3StorageUsed(TestCase):
     @override_settings(
-        DEFAULT_FILE_STORAGE="django.core.files.storage.FileSystemStorage"
+        STORAGES={"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"}}
     )
     def test_should_return_false_if_not(self):
         self.assertIs(is_s3_boto3_storage_used(), False)
 
-    @override_settings(DEFAULT_FILE_STORAGE="storages.backends.s3boto3.S3Boto3Storage")
+    @override_settings(
+        STORAGES={"default": {"BACKEND": "storages.backends.s3boto3.S3Boto3Storage"}}
+    )
     def test_should_return_true_if_yes(self):
         self.assertIs(is_s3_boto3_storage_used(), True)
 
diff --git a/wagtail_storages/tests/test_wagtail_hooks.py b/wagtail_storages/tests/test_wagtail_hooks.py
index 1e83306..838c290 100644
--- a/wagtail_storages/tests/test_wagtail_hooks.py
+++ b/wagtail_storages/tests/test_wagtail_hooks.py
@@ -12,7 +12,7 @@
 @mock_aws
 class TestWagtailHooks(CreateBucket, TestCase):
     @override_settings(
-        DEFAULT_FILE_STORAGE="django.core.files.storage.FileSystemStorage"
+        STORAGES={"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"}}
     )
     def test_non_s3_storage_returns_no_response(self):
         # The hook should not return a response if S3 storage is not being