django_custom_user_migration will help you create a migration to using a custom User model with Django
Project description
django_custom_user_migration creates migrations for you to move an existing Django project that uses django.contrib.auth.models.User to using a custom user model.
Free software: BSD license
Use case
You are currently using Django’s django.contrib.auth.models.User model in a deployed project, but want to migrate to a model that is under your own control, or provided by a 3rd party.
Prerequisites
Django 1.8 or later
Python 2.7 or Python 3.3+
You must have ensured that everywhere in your project (including 3rd party libraries) you are using AUTH_USER_MODEL and django.contrib.auth.get_user_model() rather than "auth.User" and django.contrib.auth.models.User.
Usage
There 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.
Install django_custom_user_migration to your project:
pip install django_custom_user_migration
Add "django_custom_user_migration" to your INSTALLED_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’s auth.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 it accounts from now on:
# accounts/models.py from django_custom_user_migration.models import AbstractUser class User(AbstractUser): pass
The model can be called anything you want. Remember to add this app to your INSTALLED_APPS.
Don’t add additional fields at this point, and don’t change AUTH_USER_MODEL yet.
We avoid using django.contrib.auth.models.AbstractUser at this point, or a user model from some 3rd party library, because we get problems with related_name clashes that we can’t work around. Later on, we’ll change to inheriting from django.contrib.auth.AbstractUser, and then to another model if necessary.
Create a normal migration to create the table for this:
./manage.py makemigrations accounts
This migration must be 0001_initial or you will have problems later on, as mentioned in the docs for AUTH_USER_MODEL.
The migration will also create M2M tables for the M2M fields specified on AbstractUser itself.
Create a data migration that will populate these tables from auth.User:
./manage.py create_custom_user_populate_migration auth.User accounts.User
All the commands to create migrations take arguments <from_model> <to_model> like this.
Create a schema migration that will alter every FK that points at auth.User to point at your model instead:
./manage.py create_custom_user_schema_migration auth.User accounts.User
Create a data migration that will fix up the contenttypes tables:
./manage.py create_custom_user_contenttypes_migration auth.User accounts.User
Change the AbstractUser import in your models.py to:
from django.contrib.auth.models import AbstractUser
Change AUTH_USER_MODEL to "accounts.User" in your settings.
Run makemigrations again:
./manage.py makemigrations accounts
This 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-user
Simplest 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 the auth.User table:
./manage.py create_custom_user_empty_migration auth.User accounts.User
Run all the migrations:
./manage.py migrate
Test 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 the django_custom_user_migration.models.AbstractModel as 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 to auth.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/182604
Long term, this can be fixed by squashing the accounts migrations up to step 12 into a single migration. Use the squashmigrations command to do this, then manually edit it to remove all but the initial CreateModel operation. So the migration created should be the same as accounts 0001_initial, but it will have a replaces attribute that marks it as squashing the others. You may also need to adjust (remove) some of its dependencies.
Uninstall django_custom_user_migration, and remove it from your INSTALLED_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 your User model as required in the normal way, using migrations etc. You could even make it inherit from AbstractBaseUser or some other model instead of AbstractUser, provided that you write/generate the necessary data migrations to cope with missing fields, and update your admin and application accordingly.
Other notes
Use at own risk, make sure you back up your data first, etc. etc.
Tested on sqlite and postgres
If you have other tables with FKs to auth.User that 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 about auth.User. The main exception is django_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.
History
0.3.0 (2016-04-04)
Fixed crasher on Django 1.9
0.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 Postgres
0.1.0 (2015-08-14)
First release on PyPI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for django_custom_user_migration-0.3.0.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1f27543ff0fc7700026baefa3968631d189083d38de21398ea60e616f6ac203f |
|
MD5 | d849a391911f325ad1d91491e936e83a |
|
BLAKE2b-256 | c76a0059f0bf5416b66a827fd83d7e725a938a35fc0835e6d075bbe308019651 |
Hashes for django_custom_user_migration-0.3.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | b4eafe0f513544a50c1f9861ad3f0b455064c6d28254891b2db25a6a83bf4eaf |
|
MD5 | 58bb4dd7b744c824aa6d4884de3e1589 |
|
BLAKE2b-256 | ceeb91984d46d8eebd4ef244297458bdcff48424234c66dd9f770cfca8a5253c |