diff --git a/cms/envs/common.py b/cms/envs/common.py index 94145d2568..8daa48195f 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -959,6 +959,9 @@ INSTALLED_APPS = ( # management of user-triggered async tasks (course import/export, etc.) 'user_tasks', + + # Unusual migrations + 'database_fixups', ) diff --git a/common/djangoapps/database_fixups/__init__.py b/common/djangoapps/database_fixups/__init__.py new file mode 100644 index 0000000000..bea2d2681a --- /dev/null +++ b/common/djangoapps/database_fixups/__init__.py @@ -0,0 +1,3 @@ +""" +This app exists solely to host unusual database migrations. +""" diff --git a/common/djangoapps/database_fixups/migrations/0001_initial.py b/common/djangoapps/database_fixups/migrations/0001_initial.py new file mode 100644 index 0000000000..110104fdea --- /dev/null +++ b/common/djangoapps/database_fixups/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + +# We used to have a uniqueness constraint on auth_user.email: +# https://github.com/edx/edx-platform/commit/c52727b0e0fb241d8211900975d3b69fe5a1bd57 +# +# That constraint was lost in the upgrade from Django 1.4->1.8. This migration +# adds it back. But because it might already exist in databases created +# long-enough ago, we have to do it idempotently. So we check for the +# existence of the constraint before creating it. + +def add_email_uniqueness_constraint(apps, schema_editor): + # Do we already have an email uniqueness constraint? + cursor = schema_editor.connection.cursor() + constraints = schema_editor.connection.introspection.get_constraints(cursor, "auth_user") + email_constraint = constraints.get("email", {}) + if email_constraint.get("columns") == ["email"] and email_constraint.get("unique") == True: + # We already have the constraint, we're done. + return + + # We don't have the constraint, make it. + schema_editor.execute("create unique index email on auth_user (email)") + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.RunPython(add_email_uniqueness_constraint) + ] diff --git a/common/djangoapps/database_fixups/migrations/__init__.py b/common/djangoapps/database_fixups/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/common/djangoapps/student/migrations/0010_auto_20170207_0458.py b/common/djangoapps/student/migrations/0010_auto_20170207_0458.py index e700f1ec66..901e70ebf3 100644 --- a/common/djangoapps/student/migrations/0010_auto_20170207_0458.py +++ b/common/djangoapps/student/migrations/0010_auto_20170207_0458.py @@ -26,9 +26,5 @@ class Migration(migrations.Migration): # ) operations = [ - migrations.RunSQL( - # Do nothing: - "select 1", - "select 1" - ) + # Nothing to do. ] diff --git a/lms/envs/common.py b/lms/envs/common.py index 54857fbc33..832bb30d62 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2164,6 +2164,9 @@ INSTALLED_APPS = ( # Ability to detect and special-case crawler behavior 'openedx.core.djangoapps.crawlers', + + # Unusual migrations + 'database_fixups', ) # Migrations which are not in the standard module "migrations" diff --git a/openedx/core/lib/django_courseware_routers.py b/openedx/core/lib/django_courseware_routers.py index ea3a290725..5d6ecec3de 100644 --- a/openedx/core/lib/django_courseware_routers.py +++ b/openedx/core/lib/django_courseware_routers.py @@ -51,7 +51,7 @@ class StudentModuleHistoryExtendedRouter(object): """ if model_name is not None: model = hints.get('model') - if self._is_csmh(model): + if model is not None and self._is_csmh(model): return db == self.DATABASE_NAME if db == self.DATABASE_NAME: return False