How can I patch the User model while keeping existing data?

139 Views Asked by At

I have a big Django application, currently trying to upgrade from 1.6 to 1.7 (there's been attempts to upgrade straight to 1.11, but it was too much trouble, so my plan is to do it one minor at a time).

I'm following the Upgrade from South instructions, and deleted all previous migrations, but I can't get makemigrations to work. The current problem is that the auth.User model has been patched to include two new fields:

User.add_to_class('profile',
                  models.ForeignKey('access.Profile', null=True, blank=True,
                                    related_name='user_foreignkey'))
User.add_to_class('profiles', 
                  models.ManyToManyField('access.Profile', null=True,
                                         blank=True))

This patch was made in a separate app. If I just leave it where it is, I get the following error when running python manage.py makemigrations:

ValueError: Lookup failed for model referenced by field auth.User.profiles:
access.Profiles

I tried moving the add_to_class calls to the same file where Profile is defined, (after the definition), but got the same error. I also tried changing the syntax from 'access.Profile' to Profile, to no effect. Is there something else that could make this work?

If not, since I'm adding fields to the model, I figure the correct approach would be extend the AbstractUser model, as suggested by this guide. The problem with this is that the new initial migration will create a table access_user instead of using the existing auth_user. Would it be safe to simply rename auth_user to access_user and fake the migration?

Any other suggestions on how to overcome this with the least refactoring possible (management always thinks there are more urgent things than the upgrade) are welcome.

1

There are 1 best solutions below

0
Clara Daia On

tl, dr; I removed auth migrations and ran makemigrations again, that seems to have solved the problem.

I had decided to give option 2 a try. I removed the add_to_class patches, created a new class User(AbstractUser) with the new fields, removed all the existing migrations and ran makemigrations again. I got the exact same error, which made no sense because there was no longer any code relating auth.User to Profile, so I decided to investigate auth migrations. I ran

$ python migrate --list settings=settings.mysettings

and it showed a suspicious migration for auth, with yesterday's date, probably when I first tried to make migrations.

Tutorials on "how to reset all migrations" do not mention third-party installed apps, but thanks to this thread I knew where Django stored the auth migrations, so I removed both of them (the initial and the suspicious one) and reordered the INSTALLED_APPS so that access is now before django.contrib.auth. Then ran makemigrations again, and it got through access and auth migrations successfully.

I'm now getting other problems with migrations in other apps, but they don't seem to be related with this.

It might be nice to have a more intuitive way to reset all existing migrations, not only those from your repo. But then again, I don't think the add_to_class patches are the proper way to do what we wanted.