Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: do not create migration when adding custom manager to auth.User

I would like to add a custom manager to the built-in auth.User model.

I avoid switching to my own user model because of existing data in the database linking to the auth_user table.

So I add the following to models.py:

from django.contrib.auth.models import User, UserManager

class ActiveUserManager(UserManager):
    use_in_migrations = False
    def get_queryset(self):
        return super().get_queryset().filter(is_active=True)

# Monkeypatch auth.User to have custom manager
User.add_to_class('active_users', ActiveUserManager())

This seems to work, until when I run python manage.py makemigrations, Django creates a migration file 000n_auto_20181002_1721.py in myvenv/Lib/site-packages/django/contrib/auth/migrations folder, with the following content:

# imports omitted
class Migration(migrations.Migration):

    dependencies = [
        ('auth', '0008_alter_user_username_max_length'),
    ]

    operations = [
        migrations.AlterModelManagers(
            name='user',
            managers=[
                ('active_users', django.db.models.manager.Manager()),
                ('objects', django.contrib.auth.models.UserManager()),
            ],
        ),
    ]

Setting use_in_migrations = False in class ActiveUserManager does not help.

I would appreciate your suggestions on how to avoid creating this migration file or how to add a custom manager to the built-in auth.User model without this behavior. I am using Django 1.11.

like image 791
azalea Avatar asked Oct 02 '18 21:10

azalea


People also ask

How do I stop Django migration?

You can selectively disable migration for one or more Django-Models by setting managed = False in Django Model Meta options.

How do I fix migration issues in Django?

1. Run makemigrations to verify if your schema and your database are identical, but if our local initial migration is differs from the one that was applied to the database , Django won't let us know of this, and it'll say that is all good, but because of that, the local differences that you have won't be applied. 2.

Should I ignore migrations in Django?

There is only one file in migration folder that you should not ignore. That file is init.py file, If you ignore it, python will no longer look for submodules inside the directory, so any attempts to import the modules will fail.

What is the difference between Makemigrations and migrate in Django?

makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.


1 Answers

Figured it out.

I needed to also add 'objects' manager to User class, otherwise Django treats 'active_users' as the default manager.

Full code below:

from django.contrib.auth.models import User, UserManager

class ActiveUserManager(UserManager):
    use_in_migrations = False
    def get_queryset(self):
        return super().get_queryset().filter(is_active=True)

# IMPORTANT! to add 'objects' manager
# Otherwise Django treats 'active_users' as the default manager
User.add_to_class('objects', UserManager())

# Monkeypatch auth.User to have custom manager
User.add_to_class('active_users', ActiveUserManager())

I realized this by reading ModelState.fromModel(), where 'active_users' was _default_manager when 'objects' manager was not set by User.add_to_class('objects', UserManager()).

Default manager gets added to migration even when use_in_migrations = False is set.

like image 137
azalea Avatar answered Sep 20 '22 13:09

azalea