2

I have a data migration as below in which I want to use create_user method of CustomUser, get an instance of the created user, and use this instance to create instance of Partner model. It is worth mentioning that I have a Partner model that has a one-to-one relationship with CustomUser. I have two options:

# Option One:

def populate_database_create_partner(apps, schema_editor):
    Partner = apps.get_model('partners', 'Partner')

    CustomUser.objects.create_user(
        id=33,
        email='test_email@email.com',
        password='password',
        first_name='test_first_name',
        last_name="test_last_name",
        is_partner=True,
    )

    u = CustomUser.objects.get(id=33)
    partner = Partner.objects.create(user=u, )


class Migration(migrations.Migration):

    dependencies = [
        ('accounts', '0006_populate_database_createsuperuser'),
    ]

    operations = [
        migrations.RunPython(populate_database_create_partner),
    ]

In option one, I see this error:

ValueError: Cannot assign "<CustomUser: test_email@email.com>": "Partner.user" must be a "CustomUser" instance.

I then test this:

# Option Two:

def populate_database_create_partner(apps, schema_editor):
    Partner = apps.get_model('partners', 'Partner')
    CustomUser = apps.get_model('accounts', 'CustomUser')


    CustomUser.objects.create_user(
        id=33,
        email='test_email@email.com',
        password='password',
        first_name='test_first_name',
        last_name="test_last_name",
        is_partner=True,
    )

    u = CustomUser.objects.get(id=33)
    partner = Partner.objects.create(user=u, )


class Migration(migrations.Migration):

    dependencies = [
        ('accounts', '0006_populate_database_createsuperuser'),
    ]

    operations = [
        migrations.RunPython(populate_database_create_partner),
    ]

I the see this error:

CustomUser.objects.create_user(
AttributeError: 'Manager' object has no attribute 'create_user'

The create_user method does not work.

If I do not use the create_user method and simply use CustomUser.objects.create(...), I will not be able to set password in here.

Amin Ba
  • 1,603
  • 1
  • 13
  • 38

1 Answers1

0

Django only keeps limited historical information about each version of your models. One of the things it doesn't keep track of, as documented here, is custom model managers.

The good news is that there's a way to force the migrations system to use your custom manager:

You can optionally serialize managers into migrations and have them available in RunPython operations. This is done by defining a use_in_migrations attribute on the manager class.

As noted, this just allows your migration to use the version of the manager that exists when the migration is run; so, if you later make changes to it, you could break the migration. A safer alternative is to just copy the relevant create_user code into the migration itself.

Kevin Christopher Henry
  • 46,175
  • 7
  • 116
  • 102