From 30363fd71172b89db0873c72db67cb47f12bf4ea Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Sun, 28 Jul 2024 22:03:32 -0500 Subject: [PATCH] Squash/drop custom user model migration --- accounts/migrations/0001_initial.py | 40 ------ ...quashed_0008_inst_id_unique_and_updates.py | 126 ++++++++++++++++++ .../0002_user_populate_migration.py | 123 ----------------- .../migrations/0003_user_schema_migration.py | 103 -------------- .../0004_user_contenttypes_migration.py | 31 ----- .../migrations/0005_custom_user_cleanup.py | 21 --- accounts/migrations/0006_empty_auth_user.py | 121 ----------------- .../0007_migrate_user_status_data.py | 76 ----------- .../0008_inst_id_unique_and_updates.py | 34 ----- 9 files changed, 126 insertions(+), 549 deletions(-) delete mode 100644 accounts/migrations/0001_initial.py create mode 100644 accounts/migrations/0001_squashed_0008_inst_id_unique_and_updates.py delete mode 100644 accounts/migrations/0002_user_populate_migration.py delete mode 100644 accounts/migrations/0003_user_schema_migration.py delete mode 100644 accounts/migrations/0004_user_contenttypes_migration.py delete mode 100644 accounts/migrations/0005_custom_user_cleanup.py delete mode 100644 accounts/migrations/0006_empty_auth_user.py delete mode 100644 accounts/migrations/0007_migrate_user_status_data.py delete mode 100644 accounts/migrations/0008_inst_id_unique_and_updates.py diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py deleted file mode 100644 index 39e4d139b..000000000 --- a/accounts/migrations/0001_initial.py +++ /dev/null @@ -1,40 +0,0 @@ -import django.contrib.auth.models -import django.core.validators -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('auth', '0006_require_contenttypes_0002'), - ] - - operations = [ - migrations.CreateModel( - name='User', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(null=True, verbose_name='last login', blank=True)), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=30, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, verbose_name='username')), - ('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)), - ('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)), - ('email', models.EmailField(max_length=254, verbose_name='email address', blank=True)), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('groups', models.ManyToManyField(related_query_name='customtemp_user', related_name='customtemp_user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(related_query_name='customtemp_user', related_name='customtemp_user_set', to='auth.Permission', blank=True, help_text='Specific permissions for this user.', verbose_name='user permissions')), - ], - options={ - 'abstract': False, - 'verbose_name': 'user', - 'verbose_name_plural': 'users', - }, - managers=[ - ('objects', django.contrib.auth.models.UserManager()), - ], - ), - ] diff --git a/accounts/migrations/0001_squashed_0008_inst_id_unique_and_updates.py b/accounts/migrations/0001_squashed_0008_inst_id_unique_and_updates.py new file mode 100644 index 000000000..c4459e9dd --- /dev/null +++ b/accounts/migrations/0001_squashed_0008_inst_id_unique_and_updates.py @@ -0,0 +1,126 @@ +# Generated by Django 5.0.7 on 2024-07-29 03:01 + +import django.contrib.auth.models +import django.core.validators +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('accounts', '0001_initial'), ('accounts', '0002_user_populate_migration'), ('accounts', '0003_user_schema_migration'), ('accounts', '0004_user_contenttypes_migration'), ('accounts', '0005_custom_user_cleanup'), ('accounts', '0006_empty_auth_user'), ('accounts', '0007_migrate_user_status_data'), ('accounts', '0008_inst_id_unique_and_updates')] + + initial = True + + dependencies = [ + ('auth', '0006_require_contenttypes_0002'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='customtemp_user_set', related_query_name='customtemp_user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='customtemp_user_set', related_query_name='customtemp_user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'abstract': False, + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.AlterField( + model_name='user', + name='groups', + field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups'), + ), + migrations.AlterField( + model_name='user', + name='user_permissions', + field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions'), + ), + migrations.AddField( + model_name='user', + name='editor_mode', + field=models.CharField(choices=[('default', 'Default'), ('sublime', 'Sublime text'), ('emacs', 'Emacs'), ('vim', 'Vim')], default='default', help_text="Which key bindings you prefer when editing larger amounts of text or code. (If you do not understand what this means, leave it as 'Default'.)", max_length=20, verbose_name='Editor mode'), + ), + migrations.AddField( + model_name='user', + name='institutional_id', + field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Institutional ID'), + ), + migrations.AddField( + model_name='user', + name='institutional_id_verified', + field=models.BooleanField(default=False, help_text="Indicates that this user's institutional ID has been verified as being associated with the individual able to log in to this account.", verbose_name='Institutional ID verified'), + ), + migrations.AddField( + model_name='user', + name='key_time', + field=models.DateTimeField(blank=True, default=None, help_text='The time stamp of the sign in token.', null=True, verbose_name='Key time'), + ), + migrations.AddField( + model_name='user', + name='name_verified', + field=models.BooleanField(default=False, help_text="Indicates that this user's name has been verified as being associated with the individual able to sign in to this account.", verbose_name='Name verified'), + ), + migrations.AddField( + model_name='user', + name='sign_in_key', + field=models.CharField(blank=True, db_index=True, help_text='The sign in token sent out in email.', max_length=50, null=True, unique=True, verbose_name='Sign in key'), + ), + migrations.AddField( + model_name='user', + name='status', + field=models.CharField(choices=[('unconfirmed', 'Unconfirmed'), ('active', 'Active')], max_length=50, null=True, verbose_name='User status'), + ), + migrations.AlterField( + model_name='user', + name='email', + field=models.EmailField(blank=True, max_length=100, verbose_name='email address'), + ), + migrations.AlterField( + model_name='user', + name='first_name', + field=models.CharField(blank=True, max_length=100, verbose_name='first name'), + ), + migrations.AlterField( + model_name='user', + name='last_name', + field=models.CharField(blank=True, max_length=100, verbose_name='last name'), + ), + migrations.AlterField( + model_name='user', + name='editor_mode', + field=models.CharField(choices=[('default', 'Default'), ('sublime', 'Sublime text'), ('emacs', 'Emacs'), ('vim', 'Vim')], default='default', help_text="Which key bindings you prefer when editing larger amounts of text or code. (If you do not understand what this means, leave it as 'Default'.)", max_length=20, verbose_name='Editor mode'), + ), + migrations.AlterField( + model_name='user', + name='institutional_id', + field=models.CharField(blank=True, db_index=True, max_length=100, null=True, unique=True, verbose_name='Institutional ID'), + ), + migrations.AlterField( + model_name='user', + name='status', + field=models.CharField(choices=[('unconfirmed', 'Unconfirmed'), ('active', 'Active')], max_length=50, null=True, verbose_name='User status'), + ), + migrations.AlterField( + model_name='user', + name='username', + field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], verbose_name='username'), + ), + ] diff --git a/accounts/migrations/0002_user_populate_migration.py b/accounts/migrations/0002_user_populate_migration.py deleted file mode 100644 index 92ba93b19..000000000 --- a/accounts/migrations/0002_user_populate_migration.py +++ /dev/null @@ -1,123 +0,0 @@ -from django.db import migrations, models - -from relate.utils import ignore_no_such_table - - -def forwards(apps, schema_editor): - ignore_no_such_table(populate_table, - apps, schema_editor, - "auth", "User", - "accounts", "User") - - ignore_no_such_table(populate_table, - apps, schema_editor, - "auth", "User_groups", - "accounts", "User_groups") - - ignore_no_such_table(populate_table, - apps, schema_editor, - "auth", "User_user_permissions", - "accounts", "User_user_permissions") - - -def backwards(apps, schema_editor): - empty_table(apps, schema_editor, - "accounts", "User_user_permissions") - empty_table(apps, schema_editor, - "accounts", "User_groups") - empty_table(apps, schema_editor, - "accounts", "User") - - -def populate_table(apps, schema_editor, from_app, from_model, to_app, to_model): - # Due to swapped out models, which means that some model classes (and/or - # their auto-created M2M tables) do not exist or don't function correctly, - # it is better to use SELECT / INSERT than attempting to use ORM. - import math - - from_table_name = make_table_name(apps, from_app, from_model) - to_table_name = make_table_name(apps, to_app, to_model) - - max_id = get_max_id(schema_editor, from_table_name) - - # Use batches to avoid loading entire table into memory - BATCH_SIZE = 100 - - # Careful with off-by-one errors where max_id is a multiple of BATCH_SIZE - for batch_num in range(0, int(math.floor(max_id / BATCH_SIZE)) + 1): - start = batch_num * BATCH_SIZE - stop = start + BATCH_SIZE - ops = schema_editor.connection.ops - old_rows, old_cols = fetch_with_column_names(schema_editor, - "SELECT * FROM {} WHERE id >= %s AND id < %s;".format( - ops.quote_name(from_table_name)), - [start, stop]) - - # The column names in the new table aren't necessarily the same - # as in the old table - things like 'user_id' vs 'myuser_id'. - # We have to map them, and this seems to be good enough for our needs: - base_from_model = from_model.split("_")[0] - base_to_model = to_model.split("_")[0] - map_fk_col = lambda c: f"{base_to_model}_id".lower() if c == f"{base_from_model}_id".lower() else c - new_cols = list(map(map_fk_col, old_cols)) - - for row in old_rows: - values_sql = ", ".join(["%s"] * len(new_cols)) - columns_sql = ", ".join(ops.quote_name(col_name) for col_name in new_cols) - sql = "INSERT INTO {} ({}) VALUES ({});".format(ops.quote_name(to_table_name), - columns_sql, - values_sql) - - # could collect and do 'executemany', but sqlite doesn't let us - # execute more than one statement at once it seems. - schema_editor.execute(sql, row) - reset_sequence(apps, schema_editor, to_app, to_model) - - -def empty_table(apps, schema_editor, from_app, from_model): - from_table_name = make_table_name(apps, from_app, from_model) - ops = schema_editor.connection.ops - schema_editor.execute("DELETE FROM {};".format(ops.quote_name(from_table_name))) - - -def make_table_name(apps, app, model): - try: - m = apps.get_model(app, model) - if m._meta.db_table: - return m._meta.db_table - except LookupError: - pass # for M2M fields - return f"{app}_{model}".lower() - - -def fetch_with_column_names(schema_editor, sql, params): - c = schema_editor.connection.cursor() - c.execute(sql, params) - rows = c.fetchall() - return rows, [r[0] for r in c.description] - - -def get_max_id(schema_editor, table_name): - max_id = fetch_with_column_names(schema_editor, f"SELECT MAX(id) FROM {table_name};", [])[0][0][0] - if max_id is None: - max_id = 0 - return max_id - - -def reset_sequence(apps, schema_editor, app, model): - if schema_editor.connection.vendor == 'postgresql': - table_name = make_table_name(apps, app, model) - sequence_name = f"{table_name}_id_seq" - schema_editor.execute("SELECT setval(%s, %s, false);", [sequence_name, get_max_id(schema_editor, table_name) + 1]) - - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0001_initial'), - ] - - operations = [ - migrations.RunPython(forwards, backwards), - ] diff --git a/accounts/migrations/0003_user_schema_migration.py b/accounts/migrations/0003_user_schema_migration.py deleted file mode 100644 index 062989483..000000000 --- a/accounts/migrations/0003_user_schema_migration.py +++ /dev/null @@ -1,103 +0,0 @@ -import logging - -from django import VERSION as DJANGO_VERSION -from django.db import migrations, models - - -logger = logging.getLogger('django') - - -def forwards(apps, schema_editor): - change_foreign_keys(apps, schema_editor, - "auth", "User", - "accounts", "User") - - -def backwards(apps, schema_editor): - change_foreign_keys(apps, schema_editor, - "accounts", "User", - "auth", "User") - - -def change_foreign_keys(apps, schema_editor, from_app, from_model_name, to_app, to_model_name): - FromModel = apps.get_model(from_app, from_model_name) - ToModel = apps.get_model(to_app, to_model_name) - - # We don't make assumptions about which model is being pointed to by - # AUTH_USER_MODEL. So include fields from both FromModel and ToModel. - # Only one of them will actually have FK fields pointing to them. - - import sys - - fields = FromModel._meta.get_fields(include_hidden=True) + ToModel._meta.get_fields(include_hidden=True) - - for rel in fields: - if not hasattr(rel, 'field') or not isinstance(rel.field, models.ForeignKey): - continue - fk_field = rel.field - - f_name, f_field_name, pos_args, kw_args = fk_field.deconstruct() - - # fk_field might have been the old or new one. We need to fix things up. - old_field_kwargs = kw_args.copy() - old_field_kwargs['to'] = FromModel - old_field = fk_field.__class__(*pos_args, **old_field_kwargs) - old_field.model = fk_field.model - - new_field_kwargs = kw_args.copy() - new_field_kwargs['to'] = ToModel - new_field = fk_field.__class__(*pos_args, **new_field_kwargs) - new_field.model = fk_field.model - - if fk_field.model._meta.auto_created: - # If this is a FK that is part of an M2M on the model itself, - # we've already dealt with this, by virtue of the data migration - # that populates the auto-created M2M field. - if fk_field.model._meta.auto_created in [ToModel, FromModel]: - logger.info("Skipping {}".format(repr(rel))) - continue - - # In this case (FK fields that are part of an autogenerated M2M), - # the column name in the new M2M might be different to that in the - # old M2M. This makes things much harder, and involves duplicating - # some Django logic. - - # Build a correct ForeignKey field, as it should - # have been on FromModel - old_field.name = from_model_name.lower() - old_field.column = f"{old_field.name}_id" - - # build a correct ForeignKey field, as it should - # be on ToModel - new_field.name = to_model_name.lower() - new_field.column = f"{new_field.name}_id" - else: - old_field.name = fk_field.name - old_field.column = fk_field.column - new_field.name = fk_field.name - new_field.column = fk_field.column - - if DJANGO_VERSION < (2, 0): - show = lambda m: f"{m._meta.app_label}.{m.__name__}" - logger.info("Fixing FK in {}, col {} -> {}, from {} -> {}".format( - show(fk_field.model), - old_field.column, new_field.column, - show(old_field.remote_field.to), show(new_field.remote_field.to), - )) - - schema_editor.alter_field(fk_field.model, old_field, new_field, strict=True) - - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0002_user_populate_migration'), - ('admin', '0001_initial'), - ('auth', '0006_require_contenttypes_0002'), - ('course', '0075_course_metadata'), - ] - - operations = [ - migrations.RunPython(forwards, backwards), - ] diff --git a/accounts/migrations/0004_user_contenttypes_migration.py b/accounts/migrations/0004_user_contenttypes_migration.py deleted file mode 100644 index b2dc1b194..000000000 --- a/accounts/migrations/0004_user_contenttypes_migration.py +++ /dev/null @@ -1,31 +0,0 @@ -from django.db import migrations, models - - -def forwards(apps, schema_editor): - fix_contenttype(apps, schema_editor, - "auth", "User", - "accounts", "User") - - -def backwards(apps, schema_editor): - fix_contenttype(apps, schema_editor, - "accounts", "User", - "auth", "User") - - -def fix_contenttype(apps, schema_editor, from_app, from_model, to_app, to_model): - from_model, to_model = from_model.lower(), to_model.lower() - schema_editor.execute("UPDATE django_content_type SET app_label=%s, model=%s WHERE app_label=%s AND model=%s;", - [to_app, to_model, from_app, from_model]) - - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0003_user_schema_migration'), - ] - - operations = [ - migrations.RunPython(forwards, backwards), - ] diff --git a/accounts/migrations/0005_custom_user_cleanup.py b/accounts/migrations/0005_custom_user_cleanup.py deleted file mode 100644 index f82a18f66..000000000 --- a/accounts/migrations/0005_custom_user_cleanup.py +++ /dev/null @@ -1,21 +0,0 @@ -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0004_user_contenttypes_migration'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='groups', - field=models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', verbose_name='groups'), - ), - migrations.AlterField( - model_name='user', - name='user_permissions', - field=models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Permission', blank=True, help_text='Specific permissions for this user.', verbose_name='user permissions'), - ), - ] diff --git a/accounts/migrations/0006_empty_auth_user.py b/accounts/migrations/0006_empty_auth_user.py deleted file mode 100644 index f8fc279fa..000000000 --- a/accounts/migrations/0006_empty_auth_user.py +++ /dev/null @@ -1,121 +0,0 @@ -from django.db import migrations, models - -from relate.utils import ignore_no_such_table - - -def forwards(apps, schema_editor): - ignore_no_such_table(empty_table, - apps, schema_editor, - "auth", "User_user_permissions") - ignore_no_such_table(empty_table, - apps, schema_editor, - "auth", "User_groups") - ignore_no_such_table(empty_table, - apps, schema_editor, - "auth", "User") - - -def backwards(apps, schema_editor): - populate_table(apps, schema_editor, - "accounts", "User", - "auth", "User") - populate_table(apps, schema_editor, - "accounts", "User_groups", - "auth", "User_groups") - populate_table(apps, schema_editor, - "accounts", "User_user_permissions", - "auth", "User_user_permissions") - - -def populate_table(apps, schema_editor, from_app, from_model, to_app, to_model): - # Due to swapped out models, which means that some model classes (and/or - # their auto-created M2M tables) do not exist or don't function correctly, - # it is better to use SELECT / INSERT than attempting to use ORM. - import math - - from_table_name = make_table_name(apps, from_app, from_model) - to_table_name = make_table_name(apps, to_app, to_model) - - max_id = get_max_id(schema_editor, from_table_name) - - # Use batches to avoid loading entire table into memory - BATCH_SIZE = 100 - - # Careful with off-by-one errors where max_id is a multiple of BATCH_SIZE - for batch_num in range(0, int(math.floor(max_id / BATCH_SIZE)) + 1): - start = batch_num * BATCH_SIZE - stop = start + BATCH_SIZE - ops = schema_editor.connection.ops - old_rows, old_cols = fetch_with_column_names(schema_editor, - "SELECT * FROM {} WHERE id >= %s AND id < %s;".format( - ops.quote_name(from_table_name)), - [start, stop]) - - # The column names in the new table aren't necessarily the same - # as in the old table - things like 'user_id' vs 'myuser_id'. - # We have to map them, and this seems to be good enough for our needs: - base_from_model = from_model.split("_")[0] - base_to_model = to_model.split("_")[0] - map_fk_col = lambda c: f"{base_to_model}_id".lower() if c == f"{base_from_model}_id".lower() else c - new_cols = list(map(map_fk_col, old_cols)) - - for row in old_rows: - values_sql = ", ".join(["%s"] * len(new_cols)) - columns_sql = ", ".join(ops.quote_name(col_name) for col_name in new_cols) - sql = "INSERT INTO {} ({}) VALUES ({});".format(ops.quote_name(to_table_name), - columns_sql, - values_sql) - - # could collect and do 'executemany', but sqlite doesn't let us - # execute more than one statement at once it seems. - schema_editor.execute(sql, row) - reset_sequence(apps, schema_editor, to_app, to_model) - - -def empty_table(apps, schema_editor, from_app, from_model): - from_table_name = make_table_name(apps, from_app, from_model) - ops = schema_editor.connection.ops - schema_editor.execute("DELETE FROM {};".format(ops.quote_name(from_table_name))) - - -def make_table_name(apps, app, model): - try: - m = apps.get_model(app, model) - if m._meta.db_table: - return m._meta.db_table - except LookupError: - pass # for M2M fields - return f"{app}_{model}".lower() - - -def fetch_with_column_names(schema_editor, sql, params): - c = schema_editor.connection.cursor() - c.execute(sql, params) - rows = c.fetchall() - return rows, [r[0] for r in c.description] - - -def get_max_id(schema_editor, table_name): - max_id = fetch_with_column_names(schema_editor, f"SELECT MAX(id) FROM {table_name};", [])[0][0][0] - if max_id is None: - max_id = 0 - return max_id - - -def reset_sequence(apps, schema_editor, app, model): - if schema_editor.connection.vendor == 'postgresql': - table_name = make_table_name(apps, app, model) - sequence_name = f"{table_name}_id_seq" - schema_editor.execute("SELECT setval(%s, %s, false);", [sequence_name, get_max_id(schema_editor, table_name) + 1]) - - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0005_custom_user_cleanup'), - ] - - operations = [ - migrations.RunPython(forwards, backwards), - ] diff --git a/accounts/migrations/0007_migrate_user_status_data.py b/accounts/migrations/0007_migrate_user_status_data.py deleted file mode 100644 index 9da3c24a1..000000000 --- a/accounts/migrations/0007_migrate_user_status_data.py +++ /dev/null @@ -1,76 +0,0 @@ -# Generated by Django 1.9 on 2016-01-12 02:48 - -from django.db import migrations, models - - -def forwards(apps, schema_editor): - UserStatus = apps.get_model("course", "UserStatus") - - for ustatus in UserStatus.objects.all().select_related("user"): - user = ustatus.user - user.editor_mode = ustatus.editor_mode - user.key_time = ustatus.key_time - user.sign_in_key = ustatus.sign_in_key - user.status = ustatus.status - user.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0006_empty_auth_user'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='editor_mode', - field=models.CharField(choices=[('default', 'Default'), ('sublime', 'Sublime text'), ('emacs', 'Emacs'), ('vim', 'Vim')], default='default', help_text="Which key bindings you prefer when editing larger amounts of text or code. (If you do not understand what this means, leave it as 'Default'.)", max_length=20, verbose_name='Editor mode'), - ), - migrations.AddField( - model_name='user', - name='institutional_id', - field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Institutional ID'), - ), - migrations.AddField( - model_name='user', - name='institutional_id_verified', - field=models.BooleanField(default=False, help_text="Indicates that this user's institutional ID has been verified as being associated with the individual able to log in to this account.", verbose_name='Institutional ID verified'), - ), - migrations.AddField( - model_name='user', - name='key_time', - field=models.DateTimeField(default=None, help_text='The time stamp of the sign in token.', verbose_name='Key time', null=True, blank=True), - ), - migrations.AddField( - model_name='user', - name='name_verified', - field=models.BooleanField(default=False, help_text="Indicates that this user's name has been verified as being associated with the individual able to sign in to this account.", verbose_name='Name verified'), - ), - migrations.AddField( - model_name='user', - name='sign_in_key', - field=models.CharField(blank=True, db_index=True, help_text='The sign in token sent out in email.', max_length=50, null=True, unique=True, verbose_name='Sign in key'), - ), - migrations.AddField( - model_name='user', - name='status', - field=models.CharField(choices=[('unconfirmed', 'Unconfirmed'), ('active', 'Active')], max_length=50, null=True, verbose_name='User status'), - ), - migrations.AlterField( - model_name='user', - name='email', - field=models.EmailField(blank=True, max_length=100, verbose_name='email address'), - ), - migrations.AlterField( - model_name='user', - name='first_name', - field=models.CharField(blank=True, max_length=100, verbose_name='first name'), - ), - migrations.AlterField( - model_name='user', - name='last_name', - field=models.CharField(blank=True, max_length=100, verbose_name='last name'), - ), - migrations.RunPython(forwards), - ] diff --git a/accounts/migrations/0008_inst_id_unique_and_updates.py b/accounts/migrations/0008_inst_id_unique_and_updates.py deleted file mode 100644 index 4ca78a939..000000000 --- a/accounts/migrations/0008_inst_id_unique_and_updates.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 1.9.1 on 2016-01-15 15:10 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0007_migrate_user_status_data'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='editor_mode', - field=models.CharField(choices=[('default', 'Default'), ('sublime', 'Sublime text'), ('emacs', 'Emacs'), ('vim', 'Vim')], default='default', help_text="Which key bindings you prefer when editing larger amounts of text or code. (If you do not understand what this means, leave it as 'Default'.)", max_length=20, verbose_name='Editor mode'), - ), - migrations.AlterField( - model_name='user', - name='institutional_id', - field=models.CharField(blank=True, db_index=True, max_length=100, null=True, unique=True, verbose_name='Institutional ID'), - ), - migrations.AlterField( - model_name='user', - name='status', - field=models.CharField(choices=[('unconfirmed', 'Unconfirmed'), ('active', 'Active')], max_length=50, null=True, verbose_name='User status'), - ), - migrations.AlterField( - model_name='user', - name='username', - field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], verbose_name='username'), - ), - ]