Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
70bbd68
fix: migrations to make postgresql compatible.
Nov 4, 2024
c222853
fix: duplicate column issue
Nov 4, 2024
fe65206
fix: learning sequences migration for mysql
qasimgulzar Nov 4, 2024
2335e69
fix: mysql specific change
qasimgulzar Nov 4, 2024
4fd6ca0
fix: compile dependencies
Nov 5, 2024
1c4295c
fix: migration issue
Nov 5, 2024
60c4830
fix: broken test
Nov 5, 2024
0a9cd28
fix: using models.BigAutoField instead of custom field.
Nov 18, 2024
00b235a
fix: existing migrations.
Nov 18, 2024
2614432
fix: existing migrations.
Nov 18, 2024
8c21658
fix: mismatched migrations.
Nov 18, 2024
d096773
fix: quality issues
Nov 18, 2024
63875d9
fix: quality issues
Nov 22, 2024
78c2209
Merge branch 'master' into qasim/postgres
e0d Apr 3, 2025
fc80ce2
Merge branch 'master' into qasim/postgres
qasimgulzar Apr 8, 2025
c739e41
Merge remote-tracking branch 'openedx/master' into qasim/postgres
May 4, 2025
c0f0695
Merge branch 'master' into qasim/postgres
qasimgulzar Jul 1, 2025
03b4b00
Merge branch 'master' into qasim/postgres
qasimgulzar Aug 27, 2025
43938ac
Merge branch 'master' into qasim/postgres
qasimgulzar Sep 9, 2025
1f5c9d0
Merge branch 'master' into qasim/postgres
qasimgulzar Sep 11, 2025
499c852
fix: typo
qasimgulzar Sep 15, 2025
558f5ad
Merge branch 'master' into qasim/postgres
qasimgulzar Sep 15, 2025
22dc5f9
fix: accommodated PR feedback
qasimgulzar Sep 29, 2025
139b8a6
Merge branch 'master' into qasim/postgres
qasimgulzar Sep 29, 2025
cdd8403
fix: accommodated PR feedback
qasimgulzar Sep 29, 2025
42f9b3c
fix: putting back `UnsignedBigIntAutoField` to avoid type issue for e…
qasimgulzar Oct 1, 2025
5e73119
Merge branch 'master' into qasim/postgres
qasimgulzar Oct 1, 2025
023e5b0
Merge branch 'master' into qasim/postgres
qasimgulzar Oct 27, 2025
30811ef
fix: register adapters for locators
qasimgulzar Oct 31, 2025
6e11456
Merge branch 'master' into qasim/postgres
qasimgulzar Oct 31, 2025
c44cd5d
Merge branch 'master' into qasim/postgres
qasimgulzar Dec 2, 2025
d4049f3
Merge branch 'master' into qasim/postgres
qasimgulzar Dec 19, 2025
7df2ae2
Merge branch 'master' into qasim/postgres
qasimgulzar Dec 20, 2025
aaa8a71
fix: move models.BigAutoField to UnsignedBigIntAutoField
qasimgulzar Dec 28, 2025
c4f859c
Merge branch 'master' into qasim/postgres
qasimgulzar Dec 28, 2025
edcad98
Merge branch 'master' into qasim/postgres
qasimgulzar Jan 20, 2026
c1c287c
fix: inconsistent dependencies
qasimgulzar Jan 27, 2026
f48ad00
fix: inconsistent dependencies
qasimgulzar Jan 27, 2026
41555c9
Merge branch 'master' into qasim/postgres
qasimgulzar Jan 27, 2026
4ac2812
Merge branch 'master' into qasim/postgres
qasimgulzar Jan 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,40 @@
# Generated by Django 2.2.20 on 2021-05-07 18:29, manually modified to make "course_id" column case sensitive

from django.conf import settings
from django.db import migrations, models
from django.db import migrations, models, connection
import django.db.models.deletion
import opaque_keys.edx.django.models
import simple_history.models


def generate_split_module_sql(db_engine):
if 'mysql' in db_engine:
return 'ALTER TABLE split_modulestore_django_splitmodulestorecourseindex MODIFY course_id varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL UNIQUE;'
elif 'postgresql' in db_engine:
return """
ALTER TABLE split_modulestore_django_splitmodulestorecourseindex
ALTER COLUMN course_id TYPE VARCHAR(255),
ALTER COLUMN course_id SET NOT NULL;

ALTER TABLE split_modulestore_django_splitmodulestorecourseindex
ADD CONSTRAINT course_id_unique UNIQUE (course_id);
"""


def generate_split_history_module_sql(db_engine):
if 'mysql' in db_engine:
return 'ALTER TABLE split_modulestore_django_historicalsplitmodulestorecourseindex MODIFY course_id varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;'
elif 'postgresql' in db_engine:
return """
ALTER TABLE split_modulestore_django_historicalsplitmodulestorecourseindex
ALTER COLUMN course_id TYPE VARCHAR(255),
ALTER COLUMN course_id SET NOT NULL,
ALTER COLUMN course_id SET DATA TYPE VARCHAR(255) COLLATE "C";
"""
class Migration(migrations.Migration):

initial = True
db_engine = connection.settings_dict['ENGINE']

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
Expand Down Expand Up @@ -65,11 +90,11 @@ class Migration(migrations.Migration):
# Custom code: Convert columns to utf8_bin because we want to allow
# case-sensitive comparisons for CourseKeys, which were case-sensitive in MongoDB
migrations.RunSQL(
'ALTER TABLE split_modulestore_django_splitmodulestorecourseindex MODIFY course_id varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL UNIQUE;',
generate_split_module_sql(db_engine),
reverse_sql=migrations.RunSQL.noop,
),
migrations.RunSQL(
'ALTER TABLE split_modulestore_django_historicalsplitmodulestorecourseindex MODIFY course_id varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL;',
generate_split_history_module_sql(db_engine),
reverse_sql=migrations.RunSQL.noop,
),
]
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import User
from django.db import migrations, models
from django.db import migrations, models, transaction

USERNAME = settings.ECOMMERCE_SERVICE_WORKER_USERNAME
EMAIL = USERNAME + '@fake.email'

def forwards(apps, schema_editor):
"""Add the service user."""
User = get_user_model()
user, created = User.objects.get_or_create(username=USERNAME, email=EMAIL)
if created:
user.set_unusable_password()
user.save()
with transaction.atomic():
user, created = User.objects.get_or_create(username=USERNAME, email=EMAIL)
if created:
user.set_unusable_password()
user.save()

def backwards(apps, schema_editor):
"""Remove the service user."""
User.objects.get(username=USERNAME, email=EMAIL).delete()
with transaction.atomic():
User.objects.get(username=USERNAME, email=EMAIL).delete()

class Migration(migrations.Migration):

Expand Down
33 changes: 0 additions & 33 deletions lms/djangoapps/courseware/fields.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,3 @@
"""
Custom fields
"""


from django.db.models.fields import AutoField


class UnsignedBigIntAutoField(AutoField):
"""
An unsigned 8-byte integer for auto-incrementing primary keys.
"""
def db_type(self, connection):
if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql':
return "bigint UNSIGNED AUTO_INCREMENT"
elif connection.settings_dict['ENGINE'] == 'django.db.backends.sqlite3':
# Sqlite will only auto-increment the ROWID column. Any INTEGER PRIMARY KEY column
# is an alias for that (https://www.sqlite.org/autoinc.html). An unsigned integer
# isn't an alias for ROWID, so we have to give up on the unsigned part.
return "integer"
elif connection.settings_dict['ENGINE'] == 'django.db.backends.postgresql_psycopg2':
# Pg's bigserial is implicitly unsigned (doesn't allow negative numbers) and
# goes 1-9.2x10^18
return "BIGSERIAL"
else:
return None

def rel_db_type(self, connection):
if connection.settings_dict['ENGINE'] == 'django.db.backends.mysql':
return "bigint UNSIGNED"
elif connection.settings_dict['ENGINE'] == 'django.db.backends.sqlite3':
return "integer"
elif connection.settings_dict['ENGINE'] == 'django.db.backends.postgresql_psycopg2':
return "BIGSERIAL"
else:
return None
2 changes: 1 addition & 1 deletion lms/djangoapps/courseware/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='StudentModule',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('id', models.BigAutoField(primary_key=True, serialize=False, verbose_name='ID')),
('module_type', models.CharField(default='problem', max_length=32, db_index=True, choices=[('problem', 'problem'), ('video', 'video'), ('html', 'html'), ('course', 'course'), ('chapter', 'Section'), ('sequential', 'Subsection'), ('library_content', 'Library Content')])),
('module_state_key', UsageKeyField(max_length=255, db_column='module_id', db_index=True)),
('course_id', CourseKeyField(max_length=255, db_index=True)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ class Migration(migrations.Migration):
]

operations = [
migrations.RunPython(move_overrides_to_edx_when)
migrations.RunPython(move_overrides_to_edx_when, reverse_code=migrations.RunPython.noop)
]
23 changes: 17 additions & 6 deletions lms/djangoapps/courseware/migrations/0011_csm_id_bigint.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
# Generated by Django 1.11.23 on 2019-08-28 15:50


import lms.djangoapps.courseware.fields

from django.conf import settings
from django.db import migrations
from django.db import migrations, models
from django.db.migrations import AlterField

class CsmBigInt(AlterField):
'''
Subclass AlterField migration class to split SQL between two different databases
We can't use the normal AlterField migration operation because Django generate and routes migrations at the model
We can't use the normal AlterField migration operation because Django generates and routes migrations at the model
level and the coursewarehistoryextended_studentmodulehistoryextended table is in a different database
'''
def database_forwards(self, app_label, schema_editor, from_state, to_state):
if hasattr(schema_editor.connection, 'is_in_memory_db') and schema_editor.connection.is_in_memory_db():
# sqlite3 doesn't support 'MODIFY', so skipping during tests
return

to_model = to_state.apps.get_model(app_label, self.model_name)

if schema_editor.connection.alias == 'student_module_history':
if settings.FEATURES["ENABLE_CSMH_EXTENDED"]:
schema_editor.execute("ALTER TABLE `coursewarehistoryextended_studentmodulehistoryextended` MODIFY `student_module_id` bigint UNSIGNED NOT NULL;")
if schema_editor.connection.vendor == 'mysql':
schema_editor.execute("ALTER TABLE `coursewarehistoryextended_studentmodulehistoryextended` MODIFY `student_module_id` bigint UNSIGNED NOT NULL;")
elif schema_editor.connection.vendor == 'postgresql':
schema_editor.execute("ALTER TABLE coursewarehistoryextended_studentmodulehistoryextended ALTER COLUMN student_module_id TYPE bigint;")
elif self.allow_migrate_model(schema_editor.connection.alias, to_model):
schema_editor.execute("ALTER TABLE `courseware_studentmodule` MODIFY `id` bigint UNSIGNED AUTO_INCREMENT NOT NULL;")
if schema_editor.connection.vendor == 'postgresql':
# For PostgreSQL
schema_editor.execute("ALTER TABLE courseware_studentmodule ALTER COLUMN id SET DATA TYPE bigint;")
schema_editor.execute("ALTER TABLE courseware_studentmodule ALTER COLUMN id SET NOT NULL;")
else:
# For MySQL
schema_editor.execute("ALTER TABLE `courseware_studentmodule` MODIFY `id` bigint UNSIGNED AUTO_INCREMENT NOT NULL;")

def database_backwards(self, app_label, schema_editor, from_state, to_state):
# Make backwards migration a no-op, app will still work if column is wider than expected
Expand All @@ -33,13 +43,14 @@ class Migration(migrations.Migration):
dependencies = [
('courseware', '0010_auto_20190709_1559'),
]

if settings.FEATURES["ENABLE_CSMH_EXTENDED"]:
dependencies.append(('coursewarehistoryextended', '0002_force_studentmodule_index'))

operations = [
CsmBigInt(
model_name='studentmodule',
name='id',
field=lms.djangoapps.courseware.fields.UnsignedBigIntAutoField(primary_key=True, serialize=False),
field=models.BigAutoField(primary_key=True, serialize=False, verbose_name='ID'),
)
]
3 changes: 1 addition & 2 deletions lms/djangoapps/courseware/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
from edx_django_utils.cache.utils import RequestCache
from model_utils.models import TimeStampedModel
from opaque_keys.edx.django.models import BlockTypeKeyField, CourseKeyField, LearningContextKeyField, UsageKeyField
from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField

from openedx.core.djangolib.markup import HTML

Expand Down Expand Up @@ -86,7 +85,7 @@ class StudentModule(models.Model):
"""
objects = ChunkingManager()

id = UnsignedBigIntAutoField(primary_key=True) # pylint: disable=invalid-name
id = models.BigAutoField(verbose_name='ID', primary_key=True) # pylint: disable=invalid-name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change absolutely necessary? UnsignedBigIntAutoField shouldn't be used in anything new going forward, but changing the existing field types like this sounds like it would introduce a lot of operational risk for people who have existing sites.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ormsbee I have tested it by generating migrations for existing mysql setup, and it is not detecting it as a database change because that column is already a bigint

image image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A BigAutoField will generate a bigint column in MySQL, while UnsignedBigIntAutoField will make a bigint unsigned. Even if it's not detected as a change because it's a custom field, changing the field types like that may cause unintended consequences down the line for existing installs. For instance, say someone develops a plugin and the models include a foreign key reference to StudentModule. They're developing locally with a new dev install, so their plugin migration makes a bigint foreign key to StudentModule, and things seem to work. But when they try to package up their plugin and install it on a long-running install, that foreign key field type is incompatible because it's connecting to the existing StudentModule.id which is bigint unsigned.

We also can't alter the type of the existing table in a migration because people have installs that have billions of rows in these tables, and doing this would require locking rebuilding the table and its indexes.

So I know it's ugly, but please bring back the UnsignedBigIntAutoField so that this field's column type in MySQL remains exactly the same before and after this PR, whether it's a new or existing install.

Copy link
Contributor Author

@qasimgulzar qasimgulzar Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your commend make a lot of sense I am going to put it back. But I still feel it's not going to be a problem as the migration is already using models.AutoFIeld so It is already having django default behaviour.

0011_csm_id_bigint.py is the only migration which is using lms.djangoapps.courseware.fields.UnsignedBigIntAutoField however it's a history table and not going to conflict.

image

However I am putting it back so we get sometime to think over this issue and resolve separately.


## The XBlock/XModule type (e.g. "problem")
module_type = models.CharField(max_length=32, db_index=True)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from django.db import migrations, models
import django.db.models.deletion
from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField
from django.conf import settings

def bump_pk_start(apps, schema_editor):
Expand Down Expand Up @@ -45,7 +44,7 @@ class Migration(migrations.Migration):
('state', models.TextField(null=True, blank=True)),
('grade', models.FloatField(null=True, blank=True)),
('max_grade', models.FloatField(null=True, blank=True)),
('id', UnsignedBigIntAutoField(serialize=False, primary_key=True)),
('id', models.BigAutoField(primary_key=True, serialize=False)),
('student_module', models.ForeignKey(to='courseware.StudentModule', on_delete=django.db.models.deletion.DO_NOTHING, db_constraint=False)),
],
options={
Expand Down
3 changes: 1 addition & 2 deletions lms/djangoapps/coursewarehistoryextended/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from django.dispatch import receiver

from lms.djangoapps.courseware.models import BaseStudentModuleHistory, StudentModule
from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField


class StudentModuleHistoryExtended(BaseStudentModuleHistory):
Expand All @@ -40,7 +39,7 @@ class Meta:
),
]

id = UnsignedBigIntAutoField(primary_key=True) # pylint: disable=invalid-name
id = models.BigAutoField(primary_key=True, serialize=False) # pylint: disable=invalid-name

student_module = models.ForeignKey(StudentModule, db_index=False, db_constraint=False, on_delete=models.DO_NOTHING)

Expand Down
4 changes: 1 addition & 3 deletions lms/djangoapps/grades/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from django.db import migrations, models
from opaque_keys.edx.django.models import CourseKeyField, UsageKeyField

from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField


class Migration(migrations.Migration):

Expand All @@ -17,7 +15,7 @@ class Migration(migrations.Migration):
fields=[
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)),
('id', UnsignedBigIntAutoField(serialize=False, primary_key=True)),
('id', models.BigAutoField(primary_key=True, serialize=False)),
('user_id', models.IntegerField()),
('course_id', CourseKeyField(max_length=255)),
('usage_key', UsageKeyField(max_length=255)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from django.db import migrations, models
from opaque_keys.edx.django.models import CourseKeyField

from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField


class Migration(migrations.Migration):

Expand All @@ -18,7 +16,7 @@ class Migration(migrations.Migration):
fields=[
('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)),
('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)),
('id', UnsignedBigIntAutoField(serialize=False, primary_key=True)),
('id', models.BigAutoField(primary_key=True, serialize=False)),
('user_id', models.IntegerField(db_index=True)),
('course_id', CourseKeyField(max_length=255)),
('course_edited_timestamp', models.DateTimeField(verbose_name='Last content edit timestamp')),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
# Generated by Django 1.11.20 on 2019-06-05 13:59


from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import simple_history.models
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('grades', '0014_persistentsubsectiongradeoverridehistory'),
Expand All @@ -28,15 +27,24 @@ class Migration(migrations.Migration):
('history_id', models.AutoField(primary_key=True, serialize=False)),
('history_date', models.DateTimeField()),
('history_change_reason', models.CharField(max_length=100, null=True)),
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('grade', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='grades.PersistentSubsectionGrade')),
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('history_type',
models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
('history_user',
models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+',
to=settings.AUTH_USER_MODEL)),
],
options={
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
'verbose_name': 'historical persistent subsection grade override',
},
bases=(simple_history.models.HistoricalChanges, models.Model),
options = {
'ordering': ('-history_date', '-history_id'),
'get_latest_by': 'history_date',
'verbose_name': 'historical persistent subsection grade override',
},
bases = (simple_history.models.HistoricalChanges, models.Model),
),
migrations.AddField(
model_name='historicalpersistentsubsectiongradeoverride',
name='grade',
field=models.ForeignKey(blank=True, db_constraint=False, null=True,
on_delete=django.db.models.deletion.DO_NOTHING, related_name='+',
to='grades.PersistentSubsectionGrade'),
),
]
5 changes: 2 additions & 3 deletions lms/djangoapps/grades/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from opaque_keys.edx.keys import CourseKey, UsageKey
from simple_history.models import HistoricalRecords

from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField
from lms.djangoapps.grades import events # lint-amnesty, pylint: disable=unused-import
from openedx.core.lib.cache_utils import get_cache
from lms.djangoapps.grades.signals.signals import (
Expand Down Expand Up @@ -327,7 +326,7 @@ class Meta:
]

# primary key will need to be large for this table
id = UnsignedBigIntAutoField(primary_key=True) # pylint: disable=invalid-name
id = models.BigAutoField(primary_key=True) # pylint: disable=invalid-name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, maybe I'm just being dense here, but won't this still be a problem if I have an existing site and want to later add a foreign key that references this model? Because my existing site will have this primary key in the database as type "unsigned bigint". But the code here says it's actually an "bigint" now. So then when I make a new model that has a foreign key to PersistentSubsectionGrade, won't the migration try to generate that foreign key as type "bigint"? Which will work fine on new installs, but blow up if I have an older site?

FYI: @feanil, @bmedx

Copy link
Contributor

@ormsbee ormsbee Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you went over this before in an earlier thread, but I think there's something I'm just not understanding properly.

Thank you for your patience.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ormsbee That seems correct to me, but I haven't tested this kind of thing in years.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ormsbee I have tested it with mysql and it is not treating it as type change, I also have updated the underlaying migrations to use this type so that it doesn't cause any discrepancy for new installs. for existing users these migrations also not going to trigger even so it seems safe.
If you have any particular scenario please let me know.


user_id = models.IntegerField(blank=False)
course_id = CourseKeyField(blank=False, max_length=255)
Expand Down Expand Up @@ -581,7 +580,7 @@ class Meta:
]

# primary key will need to be large for this table
id = UnsignedBigIntAutoField(primary_key=True) # pylint: disable=invalid-name
id = models.BigAutoField(primary_key=True) # pylint: disable=invalid-name
user_id = models.IntegerField(blank=False, db_index=True)
course_id = CourseKeyField(blank=False, max_length=255)

Expand Down
Loading
Loading