ImportError in old migrations (django.utils.timezone.utc) after upgrading Python and Django

I recently upgraded my project from Django 3.2 to Django 5.2 and also updated Python to 3.13.

During this process, I noticed that some of my old migration files do not explicitly import timezone from django.utils.

import datetime
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
from django.utils.timezone import utc


class Migration(migrations.Migration):

    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('app', '0002_auto_20200712_1404'),
    ]

After the upgrade, I encountered an error when running:

python manage.py makemigrations

Error:

ImportError: cannot import name 'utc' from 'django.utils.timezone'

Problematic migration file:

An old migration contains:

from django.utils.timezone import utc

These migrations are already applied in production

I understand that:

  • Django 5 removed django.utils.timezone.utc

  • It should be replaced with datetime.timezone.utc

What I tried

Option 1: Monkey patch (works, but feels hacky)

from datetime import timezone
import django.utils.timezone as django_timezone

if not hasattr(django_timezone, "utc"):
    django_timezone.utc = timezone.utc

I added this to manage.py and wsgi.py, and it works.

However, I'm not sure if this is safe for production.


Option 2: Modify migration

from datetime import timezone
utc = timezone.utc

This also works, but I'm concerned about modifying migrations that are already applied in production.

My questions

  1. Is it safe to modify old migration files just to fix imports like this?

  2. Or is there a recommended approach to avoid modifying migrations?

    • (e.g. monkey patching django.utils.timezone.utc)

it is safe to modify an old migration if you are only fixing the import, not changing the migration logic.

the clean fix is to update the migration from:

from django.utils.timezone import utc

to:

import datetime
utc = datetime.timezone.utc

This is usually safe as it doesn't alter the migration's work or the state of the database it only changes a path of an import that has been removed.

I would avoid monkey-patching django.utils.timezone.utc in manage.py / wsgi.py except as a temporary workaround, because it hides the actual compatibility issue and makes the project depend on runtime patching.

Вернуться на верх