django-upgrade release with Django 4.2 fixers

Squid-shing away your toil.

I just released django-upgrade 1.13.0. The headline features are some new fixers targetting Django 4.2, which is currently in alpha.

Let’s walk through these new fixers. For more detail on any of them, see the Django 4.2 README section.

New headers argument in tests

Recent-ish Django versions have added easier mechanisms for reading and writing HTTP headers:

One place that was still lacking was the test client, where you needed to set headers via their WSGI names:

response = self.client.get("/", HTTP_ACCEPT="text/plain")

In Ticket #34074 I proposed a new headers argument for the test client and request factory classes. David Wobrock picked up the ticket in October. After a few rounds of review from myself and others, it was merged in November. So from Django 4.2, you can use:

self.client.get("/", headers={"accept": "text/plain"})

Much more consistent.

After the PR was merged to Django, David got to work on a adding a corresponding fixer to django-upgrade. I just got around to reviewing, fixing, and merging the PR. Thanks David!

So now django-upgrade can rewrite client calls using headers:

-response = self.client.get("/", HTTP_ACCEPT="text/plain")
+response = self.client.get("/", headers={"accept": "text/plain"})

…and instantiations of Client and RequestFactory:

 from django.test import Client
+Client(headers={"accept-language": "fr-fr"})

Support for the async versions of these classes remains to be added - see Issue #305.

After opening the django-upgrade PR, David completed the circle by running the new django-upgrade fixer on Django’s own test suite. This lead to django PR #16401, updating many tests. Lovely.

Two assert method renames

A smaller change to Django’s test framework - two renames, with deprecation of the old names:

The changes capitalize the “Set” in each - bringing the methods’ capitalization in line with the respective FormSet / QuerySet classes. I’m sure many

Michael Howitz worked on Django Ticket #33990 to make the change there. He then added the fixer to django-upgrade in PR #253. So now django-upgrade can do these replacements for you:

-self.assertFormsetError(response.context["form"], "username", ["Too long"])
+self.assertFormSetError(response.context["form"], "username", ["Too long"])

-self.assertQuerysetEqual(authors, ["Brad Dayley"], lambda a:
+self.assertQuerySetEqual(authors, ["Brad Dayley"], lambda a:

Sure, it’s automating only two fairly simple find-and-replace operations. But hopefully this will mean many developers don’t even need to understand the change or see its associated deprecation warning. Thanks Michael!

The new STORAGES setting

Django 4.2 introduces the new STORAGES setting. Like CACHES and DATABASES, this allows you to create arbitrary named storage backends, and pass them options.

STORAGES replaces the previous DEFAULT_FILE_STORAGE and STATICFILES_STORAGE settings, which are now deprecated. So you might see this warning:

RemovedInDjango51Warning: The DEFAULT_FILE_STORAGE setting is deprecated. Use STORAGES instead.

The new fixer in django-upgrade groups the old settings into STORAGES:

-DEFAULT_FILE_STORAGE = "example.storages.ExtendedFileSystemStorage"
-STATICFILES_STORAGE = "example.storages.ExtendedS3Storage"
+    "default": {
+        "BACKEND": "example.storages.ExtendedFileSystemStorage",
+    },
+    "staticfiles": {
+        "BACKEND": "example.storages.ExtendedS3Storage",
+    },

Another small “fixed that for you”.


I really like to see django-upgrade moving in step with Django. It’s my hope having a well-maintained upgrade tool (maybe one day officila) will allow Django to make slightly more daring changes.

This release also includes:

Please test Django 4.2 and django-upgrade on your projects today! There may be other fixers we can add for changes in Django 4.2—I’m open to suggestions.


Learn how to make your tests run quickly in my book Speed Up Your Django Tests.

Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts: