Reputation: 2444
For some reason, Django (3.0.7,8) is not running one of my migrations users.0002_customuser_is_service_account
when executing a TestCase
. It's not failing, it just seems to ignore it. This migration has been applied successfully to my development database, and under normal circumstances, the migrate command seems to detect it without issue.
Revert to Initial:
python manage.py migrate users 0001
Operations to perform:
Target specific migration: 0001_initial, from users
Running migrations:
Rendering model states... DONE
Unapplying users.0002_customuser_is_service_account... OK
Re-apply by auto-detecting migration
python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, csv_management, reversion, sessions, softdelete, tasks, trades, trades_portal, users
Running migrations:
Applying users.0002_customuser_is_service_account... OK
Migrations in Development Database:
But when I attempt to run this simple TestCase
, it complains that it cannot find a column.
from django.test import TestCase
from users.models import CustomUser
class TestExists(TestCase):
def test_thing(self):
CustomUser.objects.all()
python manage.py test trades_portal --no-input
django.db.utils.ProgrammingError: column "is_service_account" of relation "users_customuser" does not exist
LINE 1: ... "email", "is_staff", "is_active", "date_joined", "is_servic...
If I look at the test database after the test fails, sure enough, that column does not exist:
And looking in the migrations, the migration which adds that column was never run:
Here is the migration:
# Generated by Django 3.0.7 on 2020-06-12 14:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='customuser',
name='is_service_account',
field=models.BooleanField(default=False, help_text='Designation for whether this account receives certain actions, such as receiving emails for all users.', verbose_name='Is Service Account'),
),
]
The thing is, I tried to re-create this problem in another project, but I could not. The migrations are all applied and the test runs successfully. I am at a complete loss for what is happening here.
Upvotes: 0
Views: 300
Reputation: 2444
Turns out that
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
specified as part of a migration does not ensure that all custom user model migrations are run before this migration is run. It only seems to ensure that custom_user.migrations.0001_initial
is run.
Because of this, when a migration actually attempts to fetch or create such a custom user by using the custom user model as one of its operations, you are not guaranteed that all user model migrations have been run. Such an example is below.
def add_initial_auth(apps, schema_editor):
Group = apps.get_model('auth', 'Group')
User = get_user_model()
initial_groups = INITIAL_GROUPS
existing_groups = list(Group.objects.filter(name__in=initial_groups).values_list('name', flat=True))
Group.objects.bulk_create(
[Group(name=group_name) for group_name in initial_groups if group_name not in existing_groups]
)
_ = User.objects.create_superuser(username=settings.INITIAL_ADMIN_USERNAME,
password=settings.INITIAL_ADMIN_PASSWORD,
email=settings.INITIAL_ADMIN_EMAIL)
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [migrations.RunPython(add_initial_auth)]
The solution unfortunately is that you must specify the latest migration as a dependency:
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('users', '0002_customuser_is_service_account')
]
Upvotes: 1