srmagura/goodnight-lead

0004_addOrganizationForeignKeyToUser fails

srmagura opened this issue · 5 comments

The migration script sets the organization foreign key to 1 by default. But an organization with key=1 does not exist, so there is an error.

Applying gl_site.0004_addOrganizationForeignKeyToUser...Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: insert or update on table "gl_site_leaduserinfo" violates foreign key constraint "gl__organization_id_6bf53c31e4022f07_fk_gl_site_organization_id"
DETAIL: Key (organization_id)=(1) is not present in table "gl_site_organization".

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "manage.py", line 10, in
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.4/dist-packages/django/core/management/init.py", line 338, in execute_from_command_line
utility.execute()
File "/usr/local/lib/python3.4/dist-packages/django/core/management/init.py", line 330, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python3.4/dist-packages/django/core/management/base.py", line 390, in run_from_argv
self.execute(_args, *_cmd_options)
File "/usr/local/lib/python3.4/dist-packages/django/core/management/base.py", line 441, in execute
output = self.handle(_args, *_options)
File "/usr/local/lib/python3.4/dist-packages/django/core/management/commands/migrate.py", line 221, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/python3.4/dist-packages/django/db/migrations/executor.py", line 110, in migrate
self.apply_migration(states[migration], migration, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/python3.4/dist-packages/django/db/migrations/executor.py", line 147, in apply_migration
state = migration.apply(state, schema_editor)
File "/usr/local/lib/python3.4/dist-packages/django/db/backends/base/schema.py", line 91, in exit
self.execute(sql)
File "/usr/local/lib/python3.4/dist-packages/django/db/backends/base/schema.py", line 111, in execute
cursor.execute(sql, params)
File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python3.4/dist-packages/django/db/utils.py", line 97, in exit
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python3.4/dist-packages/django/utils/six.py", line 658, in reraise
raise value.with_traceback(tb)
File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: insert or update on table "gl_site_leaduserinfo" violates foreign key constraint "gl__organization_id_6bf53c31e4022f07_fk_gl_site_organization_id"
DETAIL: Key (organization_id)=(1) is not present in table "gl_site_organization".

The upgrade path for non null fields is a little rocky. The field needs to have a default value, otherwise the database cannot create it.

Potentially you could edit the migration file to create the organization table, create a default organization, and then link all current users to that organization, but since this is a one off thing it's easier to just create the organization manually.

See example of upgrade path in commit messages: 8fe3e7a.

Actually, I don't consider this a "one off" thing since all migrations are run when someone installs our app for the first time. I will edit the migration script to create a default organization and adding all users to it.

Update. I tested just to see what happens, and it appears that django is smart enough to handle a fresh install.

I ran the following:

~ ALTER DATABASE goodnight_lead RENAME TO goodnight_lead_bak;
~ CREATE DATABASE goodnight_lead;

$ python3 manage.py migrate

Which resulted in the following with no errors. All database tables are created successfully.

Operations to perform:
Synchronize unmigrated apps: messages, staticfiles
Apply all migrations: admin, contenttypes, gl_site, sessions, auth
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying gl_site.0001_initial... OK
Applying gl_site.0002_createOrganizations... OK
Applying gl_site.0003_removeOrganizationFromUser... OK
Applying gl_site.0004_addOrganizationForeignKeyToUser... OK
Applying gl_site.0005_addOrganizationSessions... OK
Applying gl_site.0006_addCreatedByToOrganizations... OK
Applying gl_site.0007_setOrganizationCreatedByNotNull... OK
Applying gl_site.0008_addSessionIDToUserInfo... OK
Applying gl_site.0009_setUserSessionNotNull... OK
Applying sessions.0001_initial... OK

I guess it's good to note here that unlike the previous syncdb command, migrate no longer asks to create a superuser account if one does not already exist. One can be created using
$ python3 manage.py createsuperuser

I'm going to go ahead alter migrations to create a default group and session, since they're so integral to the user registration process. We should probably do the same for future migrations that include foreign key relations that expect certain other objects to already exist in the database. Otherwise I don't know how important it is.

Done, and pushed to master. Confirmed that migrating gl_site from 0001 to 0009 with an existing user and info in the database migrated the user correctly on local. Have a look to double check, if everything looks okay we can migrate prod at any time.

Tested. Looks good, except for a very minor problem (#19).