Package: django_custom_user_migration
django_custom_user_migration creates migrations for you to move an existing
Django project that usesdjango.contrib.auth.models.Userto using a custom user
model.Free software: BSD licenseUse caseYou are currently using Django’sdjango.contrib.auth.models.Usermodel in a
deployed project, but want to migrate to a model that is under your own control, or
provided by a 3rd party.PrerequisitesDjango 1.8 or laterPython 2.7 or Python 3.3+You must have ensured that everywhere in your project (including 3rd party
libraries) you are usingAUTH_USER_MODELanddjango.contrib.auth.get_user_model()rather than"auth.User"anddjango.contrib.auth.models.User.UsageThere are a lot of steps below, but it is almost all copy/paste, and with no
complications you could be done in 5 minutes. It assumed you will perform all
these steps apart from the last in your development environment.Installdjango_custom_user_migrationto your project:pip install django_custom_user_migrationAdd"django_custom_user_migration"to yourINSTALLED_APPS.You now have some management commands for creating migrations that we
will use later.Create a custom user model which is identical to Django’sauth.User, but
in an app in your own project. For this process to work correctly, you will
need to create a new app for this model - we’ll call itaccountsfrom now
on:# accounts/models.py

from django_custom_user_migration.models import AbstractUser

class User(AbstractUser):
    passThe model can be called anything you want. Remember to add this app to yourINSTALLED_APPS.Don’t add additional fields at this point, and don’t changeAUTH_USER_MODELyet.We avoid usingdjango.contrib.auth.models.AbstractUserat this point, or
a user model from some 3rd party library, because we get problems withrelated_nameclashes that we can’t work around. Later on, we’ll change to
inheriting fromdjango.contrib.auth.AbstractUser, and then to another model
if necessary.Create a normal migration to create the table for this:./manage.py makemigrations accountsThis migration must be0001_initialor you will have problems later on,
as mentioned in the docs forAUTH_USER_MODEL.The migration will also create M2M tables for the M2M fields specified
onAbstractUseritself.Create a data migration that will populate these tables fromauth.User:./manage.py create_custom_user_populate_migration auth.User accounts.UserAll the commands to create migrations take arguments <from_model> <to_model> like this.Create a schema migration that will alter every FK that points atauth.Userto point at your model instead:./manage.py create_custom_user_schema_migration auth.User accounts.UserCreate a data migration that will fix up the contenttypes tables:./manage.py create_custom_user_contenttypes_migration auth.User accounts.UserChange theAbstractUserimport in your models.py to:from django.contrib.auth.models import AbstractUserChangeAUTH_USER_MODELto"accounts.User"in your settings.Runmakemigrationsagain:./manage.py makemigrations accountsThis creates a migration that doesn’t actually change fields, but is needed
for Django to think that everything lines up again.Do related changes for admin etc. as described in Django docs:https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-django-s-default-userSimplest version:# accounts/admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from . models import User

admin.site.register(User, UserAdmin)Create a migration that empties theauth.Usertable:./manage.py create_custom_user_empty_migration auth.User accounts.UserRun all the migrations:./manage.py migrateTest everything!Note that all migrations generated are reversible, but before running them
in reverse you should set AUTH_USER_MODEL back to"auth.User", and you
will also therefore need to use thedjango_custom_user_migration.models.AbstractModelas a base class or you
will get validation errors that prevent migrations from running.When running Django unit tests, you may have problems when Django attempts
to run your migrations in a test database. Since your AUTH_USER_MODEL no
longer points toauth.User, that table won’t be created and the
migrations which expect it to exist will fail.In the short term, this can be fixed as per this advice:http://stackoverflow.com/a/28560805/182604Long term, this can be fixed by squashing theaccountsmigrations up to
step 12 into a single migration. Use thesquashmigrationscommand to do
this, then manually edit it to remove all but the initialCreateModeloperation. So the migration created should be the same as accounts0001_initial, but it will have areplacesattribute that marks it as
squashing the others. You may also need to adjust (remove) some of its
dependencies.Uninstalldjango_custom_user_migration, and remove it from yourINSTALLED_APPS, you don’t need it any more. The migrations generated
run without it being installed.You can now deploy these migrations to your production environment and run
them in the normal way using./manage.py migrate.You can now customise yourUsermodel as required in the normal way, using
migrations etc. You could even make it inherit fromAbstractBaseUseror some
other model instead ofAbstractUser, provided that you write/generate the
necessary data migrations to cope with missing fields, and update your admin and
application accordingly.Other notesUse at own risk, make sure you back up your data first, etc. etc.Tested on sqlite and postgresIf you have other tables with FKs toauth.Userthat Django doesn’t know
about, you will have to deal with those manually with a custom migration. (In
really old Django projects, you might have old tables like ‘auth_message’
kicking around which you’ll need to delete).Almost everything included in this library is generic regarding the models
involved, and uses introspection rather than hard-coding things aboutauth.User. The main exception isdjango_custom_user_migration.models.AbstractUser, which is a copy-paste
job from Django sources.This means that you may be able to use the code here to migrate other
swappable models. This has not been tested however.History0.3.0 (2016-04-04)Fixed crasher on Django 1.90.2.0 (2015-08-20)Fixed Postgres bug with sequences not being set correctly, which
caused any subsequent inserts to fail.Expanded tests to actually test against Postgres0.1.0 (2015-08-14)First release on PyPI.